refactor(tests): replaced redundant setups, simplified exception handling, and optimized code readability. (#4710)

# Description of Changes

This pull request primarily refactors and improves the test code across
several modules, focusing on modernization, simplification, and
consistency of assertions and test setup. The changes include formatting
updates and improvements to utility methods. These updates help make the
tests easier to maintain and read, and ensure they use current best
practices.

**Test code modernization and assertion improvements:**

* Replaced legacy assertion methods such as `assertTrue(x instanceof Y)`
with more specific `assertInstanceOf` assertions in multiple test files,
improving clarity and type safety.
* Updated exception assertion checks to use `assertInstanceOf` for error
types instead of `assertTrue`, ensuring more precise test validation.
* Refactored test setup in `ResourceMonitorTest` to use `final` for
`AtomicReference` fields, clarifying intent and thread safety.
* Changed some test method signatures to remove unnecessary `throws
Exception` clauses, simplifying the test code.

**Test code simplification and cleanup:**

* Removed unused mock fields and simplified array initializations in
`AutoJobPostMappingIntegrationTest`, streamlining test setup and
reducing clutter.
* Updated YAML string initialization in
`ApplicationPropertiesDynamicYamlPropertySourceTest` to use Java text
blocks for improved readability.
* Improved null handling in assertions for collection validity checks.
* Updated byte array encoding to use `StandardCharsets.UTF_8` for
reliability and clarity.

**PDF document factory test refactoring:**

* Refactored `CustomPDFDocumentFactoryTest` to move helper methods for
inflating PDFs and writing temp files to the top of the class, and
restructured parameterized tests for better organization and
maintainability.



<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.

---------

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
This commit is contained in:
Balázs Szücs
2025-10-30 20:39:55 +01:00
committed by GitHub
parent 83922c4131
commit a7900aead8
46 changed files with 676 additions and 739 deletions

View File

@@ -5,22 +5,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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.model.ApplicationProperties;
@ExtendWith(MockitoExtension.class)
public class SPDFApplicationTest {
@Mock private Environment env;
@Mock private ApplicationProperties applicationProperties;
@InjectMocks private SPDFApplication sPDFApplication;
@BeforeEach
public void setUp() {
SPDFApplication.setServerPortStatic("8080");

View File

@@ -37,10 +37,8 @@ class MergeControllerTest {
private MockMultipartFile mockFile1;
private MockMultipartFile mockFile2;
private MockMultipartFile mockFile3;
private PDDocument mockDocument;
private PDDocument mockMergedDocument;
private PDDocumentCatalog mockCatalog;
private PDPageTree mockPages;
private PDPage mockPage1;
private PDPage mockPage2;
@@ -65,10 +63,10 @@ class MergeControllerTest {
MediaType.APPLICATION_PDF_VALUE,
"PDF content 3".getBytes());
mockDocument = mock(PDDocument.class);
PDDocument mockDocument = mock(PDDocument.class);
mockMergedDocument = mock(PDDocument.class);
mockCatalog = mock(PDDocumentCatalog.class);
mockPages = mock(PDPageTree.class);
PDPageTree mockPages = mock(PDPageTree.class);
mockPage1 = mock(PDPage.class);
mockPage2 = mock(PDPage.class);
}

View File

@@ -61,7 +61,7 @@ public class RotationControllerTest {
}
@Test
public void testRotatePDFInvalidAngle() throws IOException {
public void testRotatePDFInvalidAngle() {
// Create a mock file
MockMultipartFile mockFile =
new MockMultipartFile(

View File

@@ -213,7 +213,6 @@ public class ConvertWebsiteToPdfTest {
assertNotNull(outPathStr);
// Temp file must be deleted in finally
Path outPath = Path.of(outPathStr);
assertFalse(
Files.exists(Path.of(htmlPathStr)),
"Temp HTML file should be deleted after the call");
@@ -283,6 +282,24 @@ public class ConvertWebsiteToPdfTest {
}
}
private static MockedStatic<HttpClient> mockHttpClientReturning(String body) throws Exception {
MockedStatic<HttpClient> httpClientStatic = Mockito.mockStatic(HttpClient.class);
HttpClient.Builder builder = Mockito.mock(HttpClient.Builder.class);
HttpClient client = Mockito.mock(HttpClient.class);
HttpResponse<String> response = Mockito.mock();
httpClientStatic.when(HttpClient::newBuilder).thenReturn(builder);
when(builder.followRedirects(HttpClient.Redirect.NORMAL)).thenReturn(builder);
when(builder.connectTimeout(any(Duration.class))).thenReturn(builder);
when(builder.build()).thenReturn(client);
Mockito.doReturn(response).when(client).send(any(HttpRequest.class), any());
when(response.statusCode()).thenReturn(200);
when(response.body()).thenReturn(body);
return httpClientStatic;
}
@Test
void redirect_with_error_when_disallowed_content_detected() throws Exception {
UrlToPdfRequest request = new UrlToPdfRequest();
@@ -291,7 +308,7 @@ public class ConvertWebsiteToPdfTest {
try (MockedStatic<GeneralUtils> gu = Mockito.mockStatic(GeneralUtils.class);
MockedStatic<HttpClient> httpClient =
mockHttpClientReturning(
"<link rel=\"attachment\" href=\"file:///etc/passwd\">"); ) {
"<link rel=\"attachment\" href=\"file:///etc/passwd\">")) {
gu.when(() -> GeneralUtils.isValidURL("https://example.com")).thenReturn(true);
gu.when(() -> GeneralUtils.isURLReachable("https://example.com")).thenReturn(true);
@@ -306,23 +323,4 @@ public class ConvertWebsiteToPdfTest {
&& location.getQuery().contains("error=error.disallowedUrlContent"));
}
}
private MockedStatic<HttpClient> mockHttpClientReturning(String body) throws Exception {
MockedStatic<HttpClient> httpClientStatic = Mockito.mockStatic(HttpClient.class);
HttpClient.Builder builder = Mockito.mock(HttpClient.Builder.class);
HttpClient client = Mockito.mock(HttpClient.class);
HttpResponse<String> response = Mockito.mock(HttpResponse.class);
httpClientStatic.when(HttpClient::newBuilder).thenReturn(builder);
when(builder.followRedirects(HttpClient.Redirect.NORMAL)).thenReturn(builder);
when(builder.connectTimeout(any(Duration.class))).thenReturn(builder);
when(builder.build()).thenReturn(client);
when(client.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class)))
.thenReturn(response);
when(response.statusCode()).thenReturn(200);
when(response.body()).thenReturn(body);
return httpClientStatic;
}
}

View File

@@ -42,9 +42,7 @@ public class PdfToCbzUtilsTest {
IllegalArgumentException exception =
Assertions.assertThrows(
IllegalArgumentException.class,
() -> {
PdfToCbzUtils.convertPdfToCbz(null, 300, pdfDocumentFactory);
});
() -> PdfToCbzUtils.convertPdfToCbz(null, 300, pdfDocumentFactory));
Assertions.assertEquals("File cannot be null or empty", exception.getMessage());
}
@@ -56,9 +54,7 @@ public class PdfToCbzUtilsTest {
IllegalArgumentException exception =
Assertions.assertThrows(
IllegalArgumentException.class,
() -> {
PdfToCbzUtils.convertPdfToCbz(emptyFile, 300, pdfDocumentFactory);
});
() -> PdfToCbzUtils.convertPdfToCbz(emptyFile, 300, pdfDocumentFactory));
Assertions.assertEquals("File cannot be null or empty", exception.getMessage());
}
@@ -70,9 +66,7 @@ public class PdfToCbzUtilsTest {
IllegalArgumentException exception =
Assertions.assertThrows(
IllegalArgumentException.class,
() -> {
PdfToCbzUtils.convertPdfToCbz(nonPdfFile, 300, pdfDocumentFactory);
});
() -> PdfToCbzUtils.convertPdfToCbz(nonPdfFile, 300, pdfDocumentFactory));
Assertions.assertEquals("File must be a PDF", exception.getMessage());
}
@@ -90,9 +84,7 @@ public class PdfToCbzUtilsTest {
// structure
Assertions.assertThrows(
Exception.class,
() -> {
PdfToCbzUtils.convertPdfToCbz(pdfFile, 300, pdfDocumentFactory);
});
() -> PdfToCbzUtils.convertPdfToCbz(pdfFile, 300, pdfDocumentFactory));
// Verify that load was called
Mockito.verify(pdfDocumentFactory).load(pdfFile);

View File

@@ -116,7 +116,7 @@ class PdfVectorExportControllerTest {
void convertGhostscript_pdfPassThrough_success() throws Exception {
when(endpointConfiguration.isGroupEnabled("Ghostscript")).thenReturn(false);
byte[] content = new byte[] {1};
byte[] content = {1};
MockMultipartFile file =
new MockMultipartFile(
"fileInput", "input.pdf", MediaType.APPLICATION_PDF_VALUE, content);
@@ -131,7 +131,7 @@ class PdfVectorExportControllerTest {
}
@Test
void convertGhostscript_unsupportedFormatThrows() throws Exception {
void convertGhostscript_unsupportedFormatThrows() {
when(endpointConfiguration.isGroupEnabled("Ghostscript")).thenReturn(false);
MockMultipartFile file =
new MockMultipartFile(

View File

@@ -49,13 +49,7 @@ class PipelineProcessorTest {
PipelineConfig config = new PipelineConfig();
config.setOperations(List.of(op));
Resource file =
new ByteArrayResource("data".getBytes()) {
@Override
public String getFilename() {
return "test.pdf";
}
};
Resource file = new MyFileByteArrayResource();
List<Resource> files = List.of(file);
@@ -77,4 +71,15 @@ class PipelineProcessorTest {
assertFalse(result.isHasErrors(), "No errors should occur");
assertTrue(result.getOutputFiles().isEmpty(), "Filtered file list should be empty");
}
private static class MyFileByteArrayResource extends ByteArrayResource {
public MyFileByteArrayResource() {
super("data".getBytes());
}
@Override
public String getFilename() {
return "test.pdf";
}
}
}

View File

@@ -69,61 +69,45 @@ class RedactControllerTest {
private PDDocument realDocument;
private PDPage realPage;
// Helpers
private void testAutoRedaction(
String searchText,
boolean useRegex,
boolean wholeWordSearch,
String redactColor,
float padding,
boolean convertToImage,
boolean expectSuccess)
throws Exception {
RedactPdfRequest request = createRedactPdfRequest();
request.setListOfText(searchText);
request.setUseRegex(useRegex);
request.setWholeWordSearch(wholeWordSearch);
request.setRedactColor(redactColor);
request.setCustomPadding(padding);
request.setConvertPDFToImage(convertToImage);
try {
ResponseEntity<byte[]> response = redactController.redactPdf(request);
if (expectSuccess && response != null) {
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
verify(mockDocument, times(1)).save(any(ByteArrayOutputStream.class));
verify(mockDocument, times(1)).close();
}
} catch (Exception e) {
if (expectSuccess) {
log.info("Redaction test completed with graceful handling: {}", e.getMessage());
} else {
assertNotNull(e.getMessage());
private static byte[] createSimplePdfContent() throws IOException {
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage(PDRectangle.A4);
doc.addPage(page);
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
contentStream.beginText();
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), 12);
contentStream.newLineAtOffset(100, 700);
contentStream.showText("This is a simple PDF.");
contentStream.endText();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.save(baos);
return baos.toByteArray();
}
}
private void testManualRedaction(List<RedactionArea> redactionAreas, boolean convertToImage)
throws Exception {
ManualRedactPdfRequest request = createManualRedactPdfRequest();
request.setRedactions(redactionAreas);
request.setConvertPDFToImage(convertToImage);
private static List<RedactionArea> createValidRedactionAreas() {
List<RedactionArea> areas = new ArrayList<>();
try {
ResponseEntity<byte[]> response = redactController.redactPDF(request);
RedactionArea area1 = new RedactionArea();
area1.setPage(1);
area1.setX(100.0);
area1.setY(100.0);
area1.setWidth(200.0);
area1.setHeight(50.0);
area1.setColor("000000");
areas.add(area1);
if (response != null) {
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
verify(mockDocument, times(1)).save(any(ByteArrayOutputStream.class));
}
} catch (Exception e) {
log.info("Manual redaction test completed with graceful handling: {}", e.getMessage());
}
RedactionArea area2 = new RedactionArea();
area2.setPage(1);
area2.setX(300.0);
area2.setY(200.0);
area2.setWidth(150.0);
area2.setHeight(30.0);
area2.setColor("FF0000");
areas.add(area2);
return areas;
}
@BeforeEach
@@ -189,16 +173,18 @@ class RedactControllerTest {
setupRealDocument();
}
private void setupRealDocument() throws IOException {
realDocument = new PDDocument();
realPage = new PDPage(PDRectangle.A4);
realDocument.addPage(realPage);
private static List<RedactionArea> createInvalidRedactionAreas() {
List<RedactionArea> areas = new ArrayList<>();
// Set up basic page resources
PDResources resources = new PDResources();
resources.put(
COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
realPage.setResources(resources);
RedactionArea invalidArea = new RedactionArea();
invalidArea.setPage(null); // Invalid - null page
invalidArea.setX(100.0);
invalidArea.setY(100.0);
invalidArea.setWidth(200.0);
invalidArea.setHeight(50.0);
areas.add(invalidArea);
return areas;
}
@AfterEach
@@ -607,13 +593,266 @@ class RedactControllerTest {
}
}
private static List<RedactionArea> createMultipleRedactionAreas() {
List<RedactionArea> areas = new ArrayList<>();
for (int i = 0; i < 5; i++) {
RedactionArea area = new RedactionArea();
area.setPage(1);
area.setX(50.0 + (i * 60));
area.setY(50.0 + (i * 40));
area.setWidth(50.0);
area.setHeight(30.0);
area.setColor(String.format("%06X", i * 0x333333));
areas.add(area);
}
return areas;
}
private static List<RedactionArea> createOverlappingRedactionAreas() {
List<RedactionArea> areas = new ArrayList<>();
RedactionArea area1 = new RedactionArea();
area1.setPage(1);
area1.setX(100.0);
area1.setY(100.0);
area1.setWidth(200.0);
area1.setHeight(100.0);
area1.setColor("FF0000");
areas.add(area1);
RedactionArea area2 = new RedactionArea();
area2.setPage(1);
area2.setX(150.0); // Overlaps with area1
area2.setY(150.0); // Overlaps with area1
area2.setWidth(200.0);
area2.setHeight(100.0);
area2.setColor("00FF00");
areas.add(area2);
return areas;
}
// Helper for token creation
private static List<Object> createSampleTokenList() {
return List.of(
Operator.getOperator("BT"),
COSName.getPDFName("F1"),
new COSFloat(12),
Operator.getOperator("Tf"),
new COSString("Sample text"),
Operator.getOperator("Tj"),
Operator.getOperator("ET"));
}
private RedactPdfRequest createRedactPdfRequest() {
RedactPdfRequest request = new RedactPdfRequest();
request.setFileInput(mockPdfFile);
return request;
}
private ManualRedactPdfRequest createManualRedactPdfRequest() {
ManualRedactPdfRequest request = new ManualRedactPdfRequest();
request.setFileInput(mockPdfFile);
return request;
}
private static String extractTextFromTokens(List<Object> tokens) {
StringBuilder text = new StringBuilder();
for (Object token : tokens) {
if (token instanceof COSString cosString) {
text.append(cosString.getString());
} else if (token instanceof COSArray array) {
for (int i = 0; i < array.size(); i++) {
if (array.getObject(i) instanceof COSString cosString) {
text.append(cosString.getString());
}
}
}
}
return text.toString();
}
private static byte[] readAllBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
}
// Helpers
private void testAutoRedaction(
String searchText,
boolean useRegex,
boolean wholeWordSearch,
String redactColor,
float padding,
boolean convertToImage,
boolean expectSuccess) {
RedactPdfRequest request = createRedactPdfRequest();
request.setListOfText(searchText);
request.setUseRegex(useRegex);
request.setWholeWordSearch(wholeWordSearch);
request.setRedactColor(redactColor);
request.setCustomPadding(padding);
request.setConvertPDFToImage(convertToImage);
try {
ResponseEntity<byte[]> response = redactController.redactPdf(request);
if (expectSuccess && response != null) {
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
assertNotNull(response.getBody());
assertTrue(response.getBody().length > 0);
verify(mockDocument, times(1)).save(any(ByteArrayOutputStream.class));
verify(mockDocument, times(1)).close();
}
} catch (Exception e) {
if (expectSuccess) {
log.info("Redaction test completed with graceful handling: {}", e.getMessage());
} else {
assertNotNull(e.getMessage());
}
}
}
private void testManualRedaction(List<RedactionArea> redactionAreas, boolean convertToImage) {
ManualRedactPdfRequest request = createManualRedactPdfRequest();
request.setRedactions(redactionAreas);
request.setConvertPDFToImage(convertToImage);
try {
ResponseEntity<byte[]> response = redactController.redactPDF(request);
if (response != null) {
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
verify(mockDocument, times(1)).save(any(ByteArrayOutputStream.class));
}
} catch (Exception e) {
log.info("Manual redaction test completed with graceful handling: {}", e.getMessage());
}
}
private void setupRealDocument() {
realDocument = new PDDocument();
realPage = new PDPage(PDRectangle.A4);
realDocument.addPage(realPage);
// Set up basic page resources
PDResources resources = new PDResources();
resources.put(
COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
realPage.setResources(resources);
}
// Helper methods for real PDF content creation
private void createRealPageWithSimpleText(String text) throws IOException {
realPage = new PDPage(PDRectangle.A4);
while (realDocument.getNumberOfPages() > 0) {
realDocument.removePage(0);
}
realDocument.addPage(realPage);
realPage.setResources(new PDResources());
realPage.getResources()
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText(text);
contentStream.endText();
}
}
private void createRealPageWithTJArrayText() throws IOException {
realPage = new PDPage(PDRectangle.A4);
while (realDocument.getNumberOfPages() > 0) {
realDocument.removePage(0);
}
realDocument.addPage(realPage);
realPage.setResources(new PDResources());
realPage.getResources()
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("This is ");
contentStream.newLineAtOffset(-10, 0); // Simulate positioning
contentStream.showText("secret");
contentStream.newLineAtOffset(10, 0); // Reset positioning
contentStream.showText(" information");
contentStream.endText();
}
}
private void createRealPageWithMixedContent() throws IOException {
realPage = new PDPage(PDRectangle.A4);
while (realDocument.getNumberOfPages() > 0) {
realDocument.removePage(0);
}
realDocument.addPage(realPage);
realPage.setResources(new PDResources());
realPage.getResources()
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
contentStream.setLineWidth(2);
contentStream.moveTo(100, 100);
contentStream.lineTo(200, 200);
contentStream.stroke();
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("Please redact this content");
contentStream.endText();
}
}
private void createRealPageWithSpecificOperator(String operatorName) throws IOException {
createRealPageWithSimpleText("sensitive data");
}
private void createRealPageWithPositionedText() throws IOException {
realPage = new PDPage(PDRectangle.A4);
while (realDocument.getNumberOfPages() > 0) {
realDocument.removePage(0);
}
realDocument.addPage(realPage);
realPage.setResources(new PDResources());
realPage.getResources()
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("Normal text ");
contentStream.newLineAtOffset(100, 0);
contentStream.showText("confidential");
contentStream.newLineAtOffset(100, 0);
contentStream.showText(" more text");
contentStream.endText();
}
}
@Nested
@DisplayName("Error Handling and Edge Cases")
class ErrorHandlingTests {
@Test
@DisplayName("Should handle null file input gracefully")
void handleNullFileInput() throws Exception {
void handleNullFileInput() {
RedactPdfRequest request = new RedactPdfRequest();
request.setFileInput(null);
request.setListOfText("test");
@@ -630,7 +869,7 @@ class RedactControllerTest {
@Test
@DisplayName("Should handle malformed PDF gracefully")
void handleMalformedPdfGracefully() throws Exception {
void handleMalformedPdfGracefully() {
MockMultipartFile malformedFile =
new MockMultipartFile(
"fileInput",
@@ -674,7 +913,7 @@ class RedactControllerTest {
@Test
@DisplayName("Should handle null redact color gracefully")
void handleNullRedactColor() throws Exception {
void handleNullRedactColor() {
RedactPdfRequest request = createRedactPdfRequest();
request.setListOfText("test");
request.setRedactColor(null);
@@ -722,34 +961,50 @@ class RedactControllerTest {
}
}
private List<Object> getOriginalTokens() throws Exception {
// Create a new page to avoid side effects from other tests
PDPage pageForTokenExtraction = new PDPage(PDRectangle.A4);
pageForTokenExtraction.setResources(realPage.getResources());
try (PDPageContentStream contentStream =
new PDPageContentStream(realDocument, pageForTokenExtraction)) {
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("Original content");
contentStream.endText();
}
return redactController.createTokensWithoutTargetText(
realDocument, pageForTokenExtraction, Collections.emptySet(), false, false);
}
@Nested
@DisplayName("Color Decoding Utility Tests")
class ColorDecodingTests {
@Test
@DisplayName("Should decode valid hex color with hash")
void decodeValidHexColorWithHash() throws Exception {
void decodeValidHexColorWithHash() {
Color result = redactController.decodeOrDefault("#FF0000");
assertEquals(Color.RED, result);
}
@Test
@DisplayName("Should decode valid hex color without hash")
void decodeValidHexColorWithoutHash() throws Exception {
void decodeValidHexColorWithoutHash() {
Color result = redactController.decodeOrDefault("FF0000");
assertEquals(Color.RED, result);
}
@Test
@DisplayName("Should default to black for null color")
void defaultToBlackForNullColor() throws Exception {
void defaultToBlackForNullColor() {
Color result = redactController.decodeOrDefault(null);
assertEquals(Color.BLACK, result);
}
@Test
@DisplayName("Should default to black for invalid color")
void defaultToBlackForInvalidColor() throws Exception {
void defaultToBlackForInvalidColor() {
Color result = redactController.decodeOrDefault("invalid-color");
assertEquals(Color.BLACK, result);
}
@@ -761,7 +1016,7 @@ class RedactControllerTest {
"0000FF"
})
@DisplayName("Should handle various valid color formats")
void handleVariousValidColorFormats(String colorInput) throws Exception {
void handleVariousValidColorFormats(String colorInput) {
Color result = redactController.decodeOrDefault(colorInput);
assertNotNull(result);
assertTrue(
@@ -777,7 +1032,7 @@ class RedactControllerTest {
@Test
@DisplayName("Should handle short hex codes appropriately")
void handleShortHexCodes() throws Exception {
void handleShortHexCodes() {
Color result1 = redactController.decodeOrDefault("123");
Color result2 = redactController.decodeOrDefault("#12");
@@ -786,6 +1041,15 @@ class RedactControllerTest {
}
}
private String extractTextFromModifiedPage(PDPage page) throws IOException {
if (page.getContents() != null) {
try (InputStream inputStream = page.getContents()) {
return new String(readAllBytes(inputStream));
}
}
return "";
}
@Nested
@DisplayName("Content Stream Unit Tests")
class ContentStreamUnitTests {
@@ -974,7 +1238,7 @@ class RedactControllerTest {
@Test
@DisplayName("Placeholder creation should maintain text width")
void shouldCreateWidthMatchingPlaceholder() throws Exception {
void shouldCreateWidthMatchingPlaceholder() {
String originalText = "confidential";
String placeholder =
redactController.createPlaceholderWithFont(
@@ -988,7 +1252,7 @@ class RedactControllerTest {
@Test
@DisplayName("Placeholder should handle special characters")
void shouldHandleSpecialCharactersInPlaceholder() throws Exception {
void shouldHandleSpecialCharactersInPlaceholder() {
String originalText = "café naïve";
String placeholder =
redactController.createPlaceholderWithFont(
@@ -1163,270 +1427,4 @@ class RedactControllerTest {
assertTrue(response.getBody().length > 0);
}
}
private RedactPdfRequest createRedactPdfRequest() {
RedactPdfRequest request = new RedactPdfRequest();
request.setFileInput(mockPdfFile);
return request;
}
private ManualRedactPdfRequest createManualRedactPdfRequest() {
ManualRedactPdfRequest request = new ManualRedactPdfRequest();
request.setFileInput(mockPdfFile);
return request;
}
private byte[] createSimplePdfContent() throws IOException {
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage(PDRectangle.A4);
doc.addPage(page);
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
contentStream.beginText();
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), 12);
contentStream.newLineAtOffset(100, 700);
contentStream.showText("This is a simple PDF.");
contentStream.endText();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.save(baos);
return baos.toByteArray();
}
}
private List<RedactionArea> createValidRedactionAreas() {
List<RedactionArea> areas = new ArrayList<>();
RedactionArea area1 = new RedactionArea();
area1.setPage(1);
area1.setX(100.0);
area1.setY(100.0);
area1.setWidth(200.0);
area1.setHeight(50.0);
area1.setColor("000000");
areas.add(area1);
RedactionArea area2 = new RedactionArea();
area2.setPage(1);
area2.setX(300.0);
area2.setY(200.0);
area2.setWidth(150.0);
area2.setHeight(30.0);
area2.setColor("FF0000");
areas.add(area2);
return areas;
}
private List<RedactionArea> createInvalidRedactionAreas() {
List<RedactionArea> areas = new ArrayList<>();
RedactionArea invalidArea = new RedactionArea();
invalidArea.setPage(null); // Invalid - null page
invalidArea.setX(100.0);
invalidArea.setY(100.0);
invalidArea.setWidth(200.0);
invalidArea.setHeight(50.0);
areas.add(invalidArea);
return areas;
}
private List<RedactionArea> createMultipleRedactionAreas() {
List<RedactionArea> areas = new ArrayList<>();
for (int i = 0; i < 5; i++) {
RedactionArea area = new RedactionArea();
area.setPage(1);
area.setX(50.0 + (i * 60));
area.setY(50.0 + (i * 40));
area.setWidth(50.0);
area.setHeight(30.0);
area.setColor(String.format("%06X", i * 0x333333));
areas.add(area);
}
return areas;
}
private List<RedactionArea> createOverlappingRedactionAreas() {
List<RedactionArea> areas = new ArrayList<>();
RedactionArea area1 = new RedactionArea();
area1.setPage(1);
area1.setX(100.0);
area1.setY(100.0);
area1.setWidth(200.0);
area1.setHeight(100.0);
area1.setColor("FF0000");
areas.add(area1);
RedactionArea area2 = new RedactionArea();
area2.setPage(1);
area2.setX(150.0); // Overlaps with area1
area2.setY(150.0); // Overlaps with area1
area2.setWidth(200.0);
area2.setHeight(100.0);
area2.setColor("00FF00");
areas.add(area2);
return areas;
}
// Helper methods for real PDF content creation
private void createRealPageWithSimpleText(String text) throws IOException {
realPage = new PDPage(PDRectangle.A4);
while (realDocument.getNumberOfPages() > 0) {
realDocument.removePage(0);
}
realDocument.addPage(realPage);
realPage.setResources(new PDResources());
realPage.getResources()
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText(text);
contentStream.endText();
}
}
private void createRealPageWithTJArrayText() throws IOException {
realPage = new PDPage(PDRectangle.A4);
while (realDocument.getNumberOfPages() > 0) {
realDocument.removePage(0);
}
realDocument.addPage(realPage);
realPage.setResources(new PDResources());
realPage.getResources()
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("This is ");
contentStream.newLineAtOffset(-10, 0); // Simulate positioning
contentStream.showText("secret");
contentStream.newLineAtOffset(10, 0); // Reset positioning
contentStream.showText(" information");
contentStream.endText();
}
}
private void createRealPageWithMixedContent() throws IOException {
realPage = new PDPage(PDRectangle.A4);
while (realDocument.getNumberOfPages() > 0) {
realDocument.removePage(0);
}
realDocument.addPage(realPage);
realPage.setResources(new PDResources());
realPage.getResources()
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
contentStream.setLineWidth(2);
contentStream.moveTo(100, 100);
contentStream.lineTo(200, 200);
contentStream.stroke();
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("Please redact this content");
contentStream.endText();
}
}
private void createRealPageWithSpecificOperator(String operatorName) throws IOException {
createRealPageWithSimpleText("sensitive data");
}
private void createRealPageWithPositionedText() throws IOException {
realPage = new PDPage(PDRectangle.A4);
while (realDocument.getNumberOfPages() > 0) {
realDocument.removePage(0);
}
realDocument.addPage(realPage);
realPage.setResources(new PDResources());
realPage.getResources()
.put(COSName.getPDFName("F1"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
try (PDPageContentStream contentStream = new PDPageContentStream(realDocument, realPage)) {
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("Normal text ");
contentStream.newLineAtOffset(100, 0);
contentStream.showText("confidential");
contentStream.newLineAtOffset(100, 0);
contentStream.showText(" more text");
contentStream.endText();
}
}
// Helper for token creation
private List<Object> createSampleTokenList() {
return List.of(
Operator.getOperator("BT"),
COSName.getPDFName("F1"),
new COSFloat(12),
Operator.getOperator("Tf"),
new COSString("Sample text"),
Operator.getOperator("Tj"),
Operator.getOperator("ET"));
}
private List<Object> getOriginalTokens() throws Exception {
// Create a new page to avoid side effects from other tests
PDPage pageForTokenExtraction = new PDPage(PDRectangle.A4);
pageForTokenExtraction.setResources(realPage.getResources());
try (PDPageContentStream contentStream =
new PDPageContentStream(realDocument, pageForTokenExtraction)) {
contentStream.beginText();
contentStream.setFont(realPage.getResources().getFont(COSName.getPDFName("F1")), 12);
contentStream.newLineAtOffset(50, 750);
contentStream.showText("Original content");
contentStream.endText();
}
return redactController.createTokensWithoutTargetText(
realDocument, pageForTokenExtraction, Collections.emptySet(), false, false);
}
private String extractTextFromTokens(List<Object> tokens) {
StringBuilder text = new StringBuilder();
for (Object token : tokens) {
if (token instanceof COSString cosString) {
text.append(cosString.getString());
} else if (token instanceof COSArray array) {
for (int i = 0; i < array.size(); i++) {
if (array.getObject(i) instanceof COSString cosString) {
text.append(cosString.getString());
}
}
}
}
return text.toString();
}
private String extractTextFromModifiedPage(PDPage page) throws IOException {
if (page.getContents() != null) {
try (InputStream inputStream = page.getContents()) {
return new String(readAllBytes(inputStream));
}
}
return "";
}
private byte[] readAllBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
}
}

View File

@@ -16,35 +16,8 @@ import stirling.software.common.model.ApplicationProperties;
class UploadLimitServiceTest {
private UploadLimitService uploadLimitService;
private ApplicationProperties applicationProperties;
private ApplicationProperties.System systemProps;
@BeforeEach
void setUp() {
applicationProperties = mock(ApplicationProperties.class);
systemProps = mock(ApplicationProperties.System.class);
when(applicationProperties.getSystem()).thenReturn(systemProps);
uploadLimitService = new UploadLimitService();
// inject mock
try {
var field = UploadLimitService.class.getDeclaredField("applicationProperties");
field.setAccessible(true);
field.set(uploadLimitService, applicationProperties);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
@ParameterizedTest(name = "getUploadLimit case #{index}: input={0}, expected={1}")
@MethodSource("uploadLimitParams")
void shouldComputeUploadLimitCorrectly(String input, long expected) {
when(systemProps.getFileUploadLimit()).thenReturn(input);
long result = uploadLimitService.getUploadLimit();
assertEquals(expected, result);
}
static Stream<Arguments> uploadLimitParams() {
return Stream.of(
// empty or null input yields 0
@@ -56,11 +29,37 @@ class UploadLimitServiceTest {
// valid formats
Arguments.of("10KB", 10 * 1024L),
Arguments.of("2MB", 2 * 1024 * 1024L),
Arguments.of("1GB", 1L * 1024 * 1024 * 1024),
Arguments.of("1GB", (long) 1024 * 1024 * 1024),
Arguments.of("5mb", 5 * 1024 * 1024L),
Arguments.of("0MB", 0L));
}
@ParameterizedTest(name = "getUploadLimit case #{index}: input={0}, expected={1}")
@MethodSource("uploadLimitParams")
void shouldComputeUploadLimitCorrectly(String input, long expected) {
when(systemProps.getFileUploadLimit()).thenReturn(input);
long result = uploadLimitService.getUploadLimit();
assertEquals(expected, result);
}
@BeforeEach
void setUp() {
ApplicationProperties applicationProperties = mock(ApplicationProperties.class);
systemProps = mock(ApplicationProperties.System.class);
when(applicationProperties.getSystem()).thenReturn(systemProps);
uploadLimitService = new UploadLimitService();
// inject mock
try {
var field = UploadLimitService.class.getDeclaredField("applicationProperties");
field.setAccessible(true);
field.set(uploadLimitService, applicationProperties);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
@ParameterizedTest(name = "getReadableUploadLimit case #{index}: rawValue={0}, expected={1}")
@MethodSource("readableLimitParams")
void shouldReturnReadableFormat(String rawValue, String expected) {

View File

@@ -5,7 +5,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
@@ -33,12 +32,19 @@ class LanguageServiceBasicTest {
languageService = new LanguageServiceForTest(applicationProperties);
}
// Helper methods
private static Resource createMockResource(String filename) {
Resource mockResource = mock(Resource.class);
when(mockResource.getFilename()).thenReturn(filename);
return mockResource;
}
@Test
void testGetSupportedLanguages_BasicFunctionality() throws IOException {
void testGetSupportedLanguages_BasicFunctionality() {
// Set up mocked resources
Resource enResource = createMockResource("messages_en_US.properties");
Resource frResource = createMockResource("messages_fr_FR.properties");
Resource[] mockResources = new Resource[] {enResource, frResource};
Resource[] mockResources = {enResource, frResource};
// Configure the test service
((LanguageServiceForTest) languageService).setMockResources(mockResources);
@@ -53,14 +59,13 @@ class LanguageServiceBasicTest {
}
@Test
void testGetSupportedLanguages_FilteringInvalidFiles() throws IOException {
void testGetSupportedLanguages_FilteringInvalidFiles() {
// Set up mocked resources with invalid files
Resource[] mockResources =
new Resource[] {
createMockResource("messages_en_US.properties"), // Valid
createMockResource("invalid_file.properties"), // Invalid
createMockResource(null) // Null filename
};
Resource[] mockResources = {
createMockResource("messages_en_US.properties"), // Valid
createMockResource("invalid_file.properties"), // Invalid
createMockResource(null) // Null filename
};
// Configure the test service
((LanguageServiceForTest) languageService).setMockResources(mockResources);
@@ -77,15 +82,14 @@ class LanguageServiceBasicTest {
}
@Test
void testGetSupportedLanguages_WithRestrictions() throws IOException {
void testGetSupportedLanguages_WithRestrictions() {
// Set up test resources
Resource[] mockResources =
new Resource[] {
createMockResource("messages_en_US.properties"),
createMockResource("messages_fr_FR.properties"),
createMockResource("messages_de_DE.properties"),
createMockResource("messages_en_GB.properties")
};
Resource[] mockResources = {
createMockResource("messages_en_US.properties"),
createMockResource("messages_fr_FR.properties"),
createMockResource("messages_de_DE.properties"),
createMockResource("messages_en_GB.properties")
};
// Configure the test service
((LanguageServiceForTest) languageService).setMockResources(mockResources);
@@ -104,13 +108,6 @@ class LanguageServiceBasicTest {
assertFalse(supportedLanguages.contains("de_DE"), "Restricted language should be excluded");
}
// Helper methods
private Resource createMockResource(String filename) {
Resource mockResource = mock(Resource.class);
when(mockResource.getFilename()).thenReturn(filename);
return mockResource;
}
// Test subclass
private static class LanguageServiceForTest extends LanguageService {
private Resource[] mockResources;
@@ -124,7 +121,7 @@ class LanguageServiceBasicTest {
}
@Override
protected Resource[] getResourcesFromPattern(String pattern) throws IOException {
protected Resource[] getResourcesFromPattern(String pattern) {
return mockResources;
}
}

View File

@@ -15,7 +15,6 @@ import java.util.Set;
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 stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Ui;
@@ -24,10 +23,15 @@ class LanguageServiceTest {
private LanguageService languageService;
private ApplicationProperties applicationProperties;
private PathMatchingResourcePatternResolver mockedResolver;
private static Resource createMockResource(String filename) {
Resource mockResource = mock(Resource.class);
when(mockResource.getFilename()).thenReturn(filename);
return mockResource;
}
@BeforeEach
void setUp() throws Exception {
void setUp() {
// Mock ApplicationProperties
applicationProperties = mock(ApplicationProperties.class);
Ui ui = mock(Ui.class);
@@ -38,7 +42,7 @@ class LanguageServiceTest {
}
@Test
void testGetSupportedLanguages_NoRestrictions() throws IOException {
void testGetSupportedLanguages_NoRestrictions() {
// Setup
Set<String> expectedLanguages =
new HashSet<>(Arrays.asList("en_US", "fr_FR", "de_DE", "en_GB"));
@@ -61,7 +65,7 @@ class LanguageServiceTest {
}
@Test
void testGetSupportedLanguages_WithRestrictions() throws IOException {
void testGetSupportedLanguages_WithRestrictions() {
// Setup
Set<String> expectedLanguages =
new HashSet<>(Arrays.asList("en_US", "fr_FR", "de_DE", "en_GB"));
@@ -87,7 +91,7 @@ class LanguageServiceTest {
}
@Test
void testGetSupportedLanguages_ExceptionHandling() throws IOException {
void testGetSupportedLanguages_ExceptionHandling() {
// Setup - make resolver throw an exception
((LanguageServiceForTest) languageService).setShouldThrowException(true);
@@ -98,19 +102,24 @@ class LanguageServiceTest {
assertTrue(supportedLanguages.isEmpty(), "Should return empty set on exception");
}
// Helper methods to create mock resources
private Resource[] createMockResources(Set<String> languages) {
return languages.stream()
.map(lang -> createMockResource("messages_" + lang + ".properties"))
.toArray(Resource[]::new);
}
@Test
void testGetSupportedLanguages_FilteringNonMatchingFiles() throws IOException {
void testGetSupportedLanguages_FilteringNonMatchingFiles() {
// Setup with some valid and some invalid filenames
Resource[] mixedResources =
new Resource[] {
createMockResource("messages_en_US.properties"),
createMockResource(
"messages_en_GB.properties"), // Explicitly add en_GB resource
createMockResource("messages_fr_FR.properties"),
createMockResource("not_a_messages_file.properties"),
createMockResource("messages_.properties"), // Invalid format
createMockResource(null) // Null filename
};
Resource[] mixedResources = {
createMockResource("messages_en_US.properties"),
createMockResource("messages_en_GB.properties"), // Explicitly add en_GB resource
createMockResource("messages_fr_FR.properties"),
createMockResource("not_a_messages_file.properties"),
createMockResource("messages_.properties"), // Invalid format
createMockResource(null) // Null filename
};
((LanguageServiceForTest) languageService).setMockResources(mixedResources);
when(applicationProperties.getUi().getLanguages()).thenReturn(Collections.emptyList());
@@ -132,19 +141,6 @@ class LanguageServiceTest {
// language codes
}
// Helper methods to create mock resources
private Resource[] createMockResources(Set<String> languages) {
return languages.stream()
.map(lang -> createMockResource("messages_" + lang + ".properties"))
.toArray(Resource[]::new);
}
private Resource createMockResource(String filename) {
Resource mockResource = mock(Resource.class);
when(mockResource.getFilename()).thenReturn(filename);
return mockResource;
}
// Test subclass that allows us to control the resource resolver
private static class LanguageServiceForTest extends LanguageService {
private Resource[] mockResources;

View File

@@ -24,6 +24,24 @@ class PdfImageRemovalServiceTest {
service = new PdfImageRemovalService();
}
// Helper method for matching COSName in verification
private static COSName eq(final COSName value) {
return Mockito.argThat(
new org.mockito.ArgumentMatcher<>() {
@Override
public boolean matches(COSName argument) {
if (argument == null && value == null) return true;
if (argument == null || value == null) return false;
return argument.getName().equals(value.getName());
}
@Override
public String toString() {
return "eq(" + (value != null ? value.getName() : "null") + ")";
}
});
}
@Test
void testRemoveImagesFromPdf_WithImages() throws IOException {
// Mock PDF document and its components
@@ -54,7 +72,7 @@ class PdfImageRemovalServiceTest {
when(resources.isImageXObject(nonImg)).thenReturn(false);
// Execute the method
PDDocument result = service.removeImagesFromPdf(document);
service.removeImagesFromPdf(document);
// Verify that images were removed
verify(resources, times(1)).put(eq(img1), Mockito.<PDXObject>isNull());
@@ -83,7 +101,7 @@ class PdfImageRemovalServiceTest {
when(resources.getXObjectNames()).thenReturn(emptyList);
// Execute the method
PDDocument result = service.removeImagesFromPdf(document);
service.removeImagesFromPdf(document);
// Verify that no modifications were made
verify(resources, never()).put(any(COSName.class), any(PDXObject.class));
@@ -119,28 +137,10 @@ class PdfImageRemovalServiceTest {
when(resources2.isImageXObject(img2)).thenReturn(true);
// Execute the method
PDDocument result = service.removeImagesFromPdf(document);
service.removeImagesFromPdf(document);
// Verify that images were removed from both pages
verify(resources1, times(1)).put(eq(img1), Mockito.<PDXObject>isNull());
verify(resources2, times(1)).put(eq(img2), Mockito.<PDXObject>isNull());
}
// Helper method for matching COSName in verification
private static COSName eq(final COSName value) {
return Mockito.argThat(
new org.mockito.ArgumentMatcher<COSName>() {
@Override
public boolean matches(COSName argument) {
if (argument == null && value == null) return true;
if (argument == null || value == null) return false;
return argument.getName().equals(value.getName());
}
@Override
public String toString() {
return "eq(" + (value != null ? value.getName() : "null") + ")";
}
});
}
}

View File

@@ -26,19 +26,17 @@ import stirling.software.common.service.UserServiceInterface;
class PdfMetadataServiceBasicTest {
private ApplicationProperties applicationProperties;
private UserServiceInterface userService;
private PdfMetadataService pdfMetadataService;
private final String STIRLING_PDF_LABEL = "Stirling PDF";
@BeforeEach
void setUp() {
// Set up mocks for application properties' nested objects
applicationProperties = mock(ApplicationProperties.class);
ApplicationProperties applicationProperties = mock(ApplicationProperties.class);
Premium premium = mock(Premium.class);
ProFeatures proFeatures = mock(ProFeatures.class);
CustomMetadata customMetadata = mock(CustomMetadata.class);
userService = mock(UserServiceInterface.class);
UserServiceInterface userService = mock(UserServiceInterface.class);
when(applicationProperties.getPremium()).thenReturn(premium);
when(premium.getProFeatures()).thenReturn(proFeatures);

View File

@@ -24,16 +24,14 @@ class SignatureServiceTest {
@TempDir Path tempDir;
private SignatureService signatureService;
private Path personalSignatureFolder;
private Path sharedSignatureFolder;
private final String ALL_USERS_FOLDER = "ALL_USERS";
private final String TEST_USER = "testUser";
@BeforeEach
void setUp() throws IOException {
// Set up our test directory structure
personalSignatureFolder = tempDir.resolve(TEST_USER);
sharedSignatureFolder = tempDir.resolve(ALL_USERS_FOLDER);
Path personalSignatureFolder = tempDir.resolve(TEST_USER);
String ALL_USERS_FOLDER = "ALL_USERS";
Path sharedSignatureFolder = tempDir.resolve(ALL_USERS_FOLDER);
Files.createDirectories(personalSignatureFolder);
Files.createDirectories(sharedSignatureFolder);
@@ -239,7 +237,7 @@ class SignatureServiceTest {
}
@Test
void testGetAvailableSignatures_EmptyUsername() throws IOException {
void testGetAvailableSignatures_EmptyUsername() {
// Mock static method for each test
try (MockedStatic<InstallationPathConfig> mockedConfig =
mockStatic(InstallationPathConfig.class)) {
@@ -265,7 +263,7 @@ class SignatureServiceTest {
}
@Test
void testGetAvailableSignatures_NonExistentUser() throws IOException {
void testGetAvailableSignatures_NonExistentUser() {
// Mock static method for each test
try (MockedStatic<InstallationPathConfig> mockedConfig =
mockStatic(InstallationPathConfig.class)) {

View File

@@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.util.Map;
import java.util.Objects;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -80,7 +81,7 @@ class JobControllerTest {
@SuppressWarnings("unchecked")
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
assertEquals(mockResult, responseBody.get("jobResult"));
assertEquals(mockResult, Objects.requireNonNull(responseBody).get("jobResult"));
@SuppressWarnings("unchecked")
Map<String, Object> queueInfo = (Map<String, Object>) responseBody.get("queueInfo");
@@ -145,7 +146,8 @@ class JobControllerTest {
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(contentType, response.getHeaders().getFirst("Content-Type"));
assertTrue(
response.getHeaders().getFirst("Content-Disposition").contains(originalFileName));
Objects.requireNonNull(response.getHeaders().getFirst("Content-Disposition"))
.contains(originalFileName));
assertEquals(fileContent, response.getBody());
}
@@ -166,7 +168,7 @@ class JobControllerTest {
// Assert
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertTrue(response.getBody().toString().contains(errorMessage));
assertTrue(Objects.requireNonNull(response.getBody()).toString().contains(errorMessage));
}
@Test
@@ -185,7 +187,7 @@ class JobControllerTest {
// Assert
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertTrue(response.getBody().toString().contains("not complete"));
assertTrue(Objects.requireNonNull(response.getBody()).toString().contains("not complete"));
}
@Test
@@ -221,7 +223,10 @@ class JobControllerTest {
// Assert
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
assertTrue(response.getBody().toString().contains("Error retrieving file"));
assertTrue(
Objects.requireNonNull(response.getBody())
.toString()
.contains("Error retrieving file"));
}
/*
@@ -285,7 +290,8 @@ class JobControllerTest {
@SuppressWarnings("unchecked")
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
assertEquals("Job cancelled successfully", responseBody.get("message"));
assertEquals(
"Job cancelled successfully", Objects.requireNonNull(responseBody).get("message"));
assertTrue((Boolean) responseBody.get("wasQueued"));
assertEquals(2, responseBody.get("queuePosition"));
@@ -317,7 +323,8 @@ class JobControllerTest {
@SuppressWarnings("unchecked")
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
assertEquals("Job cancelled successfully", responseBody.get("message"));
assertEquals(
"Job cancelled successfully", Objects.requireNonNull(responseBody).get("message"));
assertFalse((Boolean) responseBody.get("wasQueued"));
assertEquals("n/a", responseBody.get("queuePosition"));
@@ -369,7 +376,9 @@ class JobControllerTest {
@SuppressWarnings("unchecked")
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
assertEquals("Cannot cancel job that is already complete", responseBody.get("message"));
assertEquals(
"Cannot cancel job that is already complete",
Objects.requireNonNull(responseBody).get("message"));
}
@Test
@@ -391,7 +400,9 @@ class JobControllerTest {
@SuppressWarnings("unchecked")
Map<String, Object> responseBody = (Map<String, Object>) response.getBody();
assertEquals("You are not authorized to cancel this job", responseBody.get("message"));
assertEquals(
"You are not authorized to cancel this job",
Objects.requireNonNull(responseBody).get("message"));
// Verify no cancellation attempts were made
verify(jobQueue, never()).isJobQueued(anyString());