mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 03:20:46 +02:00
# Description of Changes Introduced a new `common` module for shared libs and commonly used classes. See the screenshot below for the file structure and classes that have been moved. --- <img width="452" alt="Screenshot 2025-05-22 at 11 46 56" src="https://github.com/user-attachments/assets/c9badabc-48f9-4079-b83e-7cfde0fb840f" /> <img width="470" alt="Screenshot 2025-05-22 at 11 47 30" src="https://github.com/user-attachments/assets/e8315b09-2e78-4c50-b9de-4dd9b9b0ecb1" /> ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [x] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] 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/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [x] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details.
294 lines
11 KiB
Java
294 lines
11 KiB
Java
package stirling.software.SPDF.service;
|
|
|
|
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.mockStatic;
|
|
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.List;
|
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.io.TempDir;
|
|
import org.mockito.MockedStatic;
|
|
|
|
import stirling.software.SPDF.model.SignatureFile;
|
|
import stirling.software.common.configuration.InstallationPathConfig;
|
|
|
|
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);
|
|
|
|
Files.createDirectories(personalSignatureFolder);
|
|
Files.createDirectories(sharedSignatureFolder);
|
|
|
|
// Create test signature files
|
|
Files.write(
|
|
personalSignatureFolder.resolve("personal.png"),
|
|
"personal signature content".getBytes());
|
|
Files.write(
|
|
sharedSignatureFolder.resolve("shared.jpg"), "shared signature content".getBytes());
|
|
|
|
// Use try-with-resources for mockStatic
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Initialize the service with our temp directory
|
|
signatureService = new SignatureService();
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testHasAccessToFile_PersonalFileExists() throws IOException {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test
|
|
boolean hasAccess = signatureService.hasAccessToFile(TEST_USER, "personal.png");
|
|
|
|
// Verify
|
|
assertTrue(hasAccess, "User should have access to their personal file");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testHasAccessToFile_SharedFileExists() throws IOException {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test
|
|
boolean hasAccess = signatureService.hasAccessToFile(TEST_USER, "shared.jpg");
|
|
|
|
// Verify
|
|
assertTrue(hasAccess, "User should have access to shared files");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testHasAccessToFile_FileDoesNotExist() throws IOException {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test
|
|
boolean hasAccess = signatureService.hasAccessToFile(TEST_USER, "nonexistent.png");
|
|
|
|
// Verify
|
|
assertFalse(hasAccess, "User should not have access to non-existent files");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testHasAccessToFile_InvalidFileName() {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test and verify
|
|
assertThrows(
|
|
IllegalArgumentException.class,
|
|
() -> signatureService.hasAccessToFile(TEST_USER, "../invalid.png"),
|
|
"Should throw exception for file names with directory traversal");
|
|
|
|
assertThrows(
|
|
IllegalArgumentException.class,
|
|
() -> signatureService.hasAccessToFile(TEST_USER, "invalid/file.png"),
|
|
"Should throw exception for file names with paths");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testGetAvailableSignatures() {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test
|
|
List<SignatureFile> signatures = signatureService.getAvailableSignatures(TEST_USER);
|
|
|
|
// Verify
|
|
assertEquals(2, signatures.size(), "Should return both personal and shared signatures");
|
|
|
|
// Check that we have one of each type
|
|
boolean hasPersonal =
|
|
signatures.stream()
|
|
.anyMatch(
|
|
sig ->
|
|
"personal.png".equals(sig.getFileName())
|
|
&& "Personal".equals(sig.getCategory()));
|
|
boolean hasShared =
|
|
signatures.stream()
|
|
.anyMatch(
|
|
sig ->
|
|
"shared.jpg".equals(sig.getFileName())
|
|
&& "Shared".equals(sig.getCategory()));
|
|
|
|
assertTrue(hasPersonal, "Should include personal signature");
|
|
assertTrue(hasShared, "Should include shared signature");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testGetSignatureBytes_PersonalFile() throws IOException {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test
|
|
byte[] bytes = signatureService.getSignatureBytes(TEST_USER, "personal.png");
|
|
|
|
// Verify
|
|
assertEquals(
|
|
"personal signature content",
|
|
new String(bytes),
|
|
"Should return the correct content for personal file");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testGetSignatureBytes_SharedFile() throws IOException {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test
|
|
byte[] bytes = signatureService.getSignatureBytes(TEST_USER, "shared.jpg");
|
|
|
|
// Verify
|
|
assertEquals(
|
|
"shared signature content",
|
|
new String(bytes),
|
|
"Should return the correct content for shared file");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testGetSignatureBytes_FileNotFound() {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test and verify
|
|
assertThrows(
|
|
FileNotFoundException.class,
|
|
() -> signatureService.getSignatureBytes(TEST_USER, "nonexistent.png"),
|
|
"Should throw exception for non-existent files");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testGetSignatureBytes_InvalidFileName() {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test and verify
|
|
assertThrows(
|
|
IllegalArgumentException.class,
|
|
() -> signatureService.getSignatureBytes(TEST_USER, "../invalid.png"),
|
|
"Should throw exception for file names with directory traversal");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testGetAvailableSignatures_EmptyUsername() throws IOException {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test
|
|
List<SignatureFile> signatures = signatureService.getAvailableSignatures("");
|
|
|
|
// Verify - should only have shared signatures
|
|
assertEquals(
|
|
1,
|
|
signatures.size(),
|
|
"Should return only shared signatures for empty username");
|
|
assertEquals(
|
|
"shared.jpg",
|
|
signatures.get(0).getFileName(),
|
|
"Should have the shared signature");
|
|
assertEquals(
|
|
"Shared", signatures.get(0).getCategory(), "Should be categorized as shared");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void testGetAvailableSignatures_NonExistentUser() throws IOException {
|
|
// Mock static method for each test
|
|
try (MockedStatic<InstallationPathConfig> mockedConfig =
|
|
mockStatic(InstallationPathConfig.class)) {
|
|
mockedConfig
|
|
.when(InstallationPathConfig::getSignaturesPath)
|
|
.thenReturn(tempDir.toString());
|
|
|
|
// Test
|
|
List<SignatureFile> signatures =
|
|
signatureService.getAvailableSignatures("nonExistentUser");
|
|
|
|
// Verify - should only have shared signatures
|
|
assertEquals(
|
|
1,
|
|
signatures.size(),
|
|
"Should return only shared signatures for non-existent user");
|
|
assertEquals(
|
|
"shared.jpg",
|
|
signatures.get(0).getFileName(),
|
|
"Should have the shared signature");
|
|
assertEquals(
|
|
"Shared", signatures.get(0).getCategory(), "Should be categorized as shared");
|
|
}
|
|
}
|
|
}
|