mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 11:00:47 +02:00
refactor: remove legacy Thymeleaf web UI controllers and templates (#5406)
# Description of Changes This pull request completes the removal of Thymeleaf template engine support and documentation from the Stirling-PDF codebase and developer guides, reflecting the project's full migration to a React-based frontend. It removes all references to Thymeleaf in code, configuration, and documentation, and updates guides to focus exclusively on the React SPA architecture. This streamlines the codebase and clarifies the development workflow for contributors. **Codebase cleanup: Thymeleaf removal** - Removed all commented-out Thymeleaf dependencies and related configuration beans from `build.gradle` and `AppConfig.java` (`app/common/build.gradle`, `app/common/src/main/java/stirling/software/common/configuration/AppConfig.java`) [[1]](diffhunk://#diff-2a1a21726f33b05d16451237c68d6df91a5f4a58419d839715f3f1538a9a14aeL32) [[2]](diffhunk://#diff-70792df9a0ab5675ded888c9eb8e2815c780d7b39f4bda8cf2da51d1b336899aL67-L76). - Fully commented out (as a precursor to future deletion) the `FileFallbackTemplateResolver` and `InputStreamTemplateResource` classes, which were only used for Thymeleaf template resolution (`app/common/src/main/java/stirling/software/common/configuration/FileFallbackTemplateResolver.java`, `app/common/src/main/java/stirling/software/common/model/InputStreamTemplateResource.java`) [[1]](diffhunk://#diff-e2bc7614074316b972355cb7dda47b98f75b00eb6b2ca4f143a680ab2803dcd8L1-L49) [[2]](diffhunk://#diff-ab10ee12d8de8fb77759e931170373d388bde04bad6d0e42a0ab674355ef7ef3L1-L40). **Documentation updates: React-only focus** - Removed all instructions and references to migrating or developing with Thymeleaf templates in `DeveloperGuide.md` and `ADDING_TOOLS.md`, including detailed Thymeleaf usage examples, migration steps, and translation key usage in templates [[1]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL5-R5) [[2]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL41-L43) [[3]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL103-L105) [[4]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL157) [[5]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL312) [[6]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL404-R396) [[7]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL451-L505) [[8]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL530-R467) [[9]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL585-L669) [[10]](diffhunk://#diff-ccd22fcbec8148152c8c77b85fbfe2633a6707b5ad50c2ef88fa87e2c47ea88fL699-L709) [[11]](diffhunk://#diff-e2f8148ea620602b7761e8ee24afeac1c577476630528e210fe0b22e950016ddL3-R3) [[12]](diffhunk://#diff-e2f8148ea620602b7761e8ee24afeac1c577476630528e210fe0b22e950016ddL267-R267). - Updated architecture descriptions in `CLAUDE.md` to reflect that the frontend is now exclusively a React SPA and that Thymeleaf templates have been fully replaced [[1]](diffhunk://#diff-6ebdb617a8104a7756d0cf36578ab01103dc9f07e4dc6feb751296b9c402faf7L131-R132) [[2]](diffhunk://#diff-6ebdb617a8104a7756d0cf36578ab01103dc9f07e4dc6feb751296b9c402faf7L143-L144). **Labeler configuration update** - Removed labeler rules for files related to the old Thymeleaf-based web controllers and UI directories, as these are now obsolete (`.github/labeler-config-srvaroa.yml`). These changes ensure the codebase and documentation are consistent with the new React-only frontend approach, reducing maintenance overhead and potential confusion for contributors. --- ## 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) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### 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.
This commit is contained in:
-231
@@ -1,231 +0,0 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
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.model.ApplicationProperties;
|
||||
import stirling.software.common.util.ApplicationContextProvider;
|
||||
import stirling.software.common.util.CheckProgramInstall;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ConverterWebControllerTest {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
private ConverterWebController controller;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
controller = new ConverterWebController();
|
||||
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
|
||||
}
|
||||
|
||||
private static Stream<Object[]> simpleEndpoints() {
|
||||
return Stream.of(
|
||||
new Object[] {"/img-to-pdf", "convert/img-to-pdf", "img-to-pdf"},
|
||||
new Object[] {"/cbz-to-pdf", "convert/cbz-to-pdf", "cbz-to-pdf"},
|
||||
new Object[] {"/pdf-to-cbz", "convert/pdf-to-cbz", "pdf-to-cbz"},
|
||||
new Object[] {"/cbr-to-pdf", "convert/cbr-to-pdf", "cbr-to-pdf"},
|
||||
new Object[] {"/html-to-pdf", "convert/html-to-pdf", "html-to-pdf"},
|
||||
new Object[] {"/markdown-to-pdf", "convert/markdown-to-pdf", "markdown-to-pdf"},
|
||||
new Object[] {"/pdf-to-markdown", "convert/pdf-to-markdown", "pdf-to-markdown"},
|
||||
new Object[] {"/url-to-pdf", "convert/url-to-pdf", "url-to-pdf"},
|
||||
new Object[] {"/file-to-pdf", "convert/file-to-pdf", "file-to-pdf"},
|
||||
new Object[] {"/pdf-to-pdfa", "convert/pdf-to-pdfa", "pdf-to-pdfa"},
|
||||
new Object[] {"/pdf-to-vector", "convert/pdf-to-vector", "pdf-to-vector"},
|
||||
new Object[] {"/vector-to-pdf", "convert/vector-to-pdf", "vector-to-pdf"},
|
||||
new Object[] {"/pdf-to-xml", "convert/pdf-to-xml", "pdf-to-xml"},
|
||||
new Object[] {"/pdf-to-csv", "convert/pdf-to-csv", "pdf-to-csv"},
|
||||
new Object[] {"/pdf-to-html", "convert/pdf-to-html", "pdf-to-html"},
|
||||
new Object[] {
|
||||
"/pdf-to-presentation", "convert/pdf-to-presentation", "pdf-to-presentation"
|
||||
},
|
||||
new Object[] {"/pdf-to-text", "convert/pdf-to-text", "pdf-to-text"},
|
||||
new Object[] {"/pdf-to-word", "convert/pdf-to-word", "pdf-to-word"},
|
||||
new Object[] {"/eml-to-pdf", "convert/eml-to-pdf", "eml-to-pdf"});
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "[{index}] GET {0}")
|
||||
@MethodSource("simpleEndpoints")
|
||||
@DisplayName("Should return correct view and model for simple endpoints")
|
||||
void shouldReturnCorrectViewForSimpleEndpoints(String path, String viewName, String page)
|
||||
throws Exception {
|
||||
mockMvc.perform(get(path))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(view().name(viewName))
|
||||
.andExpect(model().attribute("currentPage", page));
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("PDF to CBR endpoint tests")
|
||||
class PdfToCbrTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return 404 when endpoint disabled")
|
||||
void shouldReturn404WhenDisabled() throws Exception {
|
||||
try (MockedStatic<ApplicationContextProvider> acp =
|
||||
org.mockito.Mockito.mockStatic(ApplicationContextProvider.class)) {
|
||||
EndpointConfiguration endpointConfig = mock(EndpointConfiguration.class);
|
||||
when(endpointConfig.isEndpointEnabled(eq("pdf-to-cbr"))).thenReturn(false);
|
||||
acp.when(() -> ApplicationContextProvider.getBean(EndpointConfiguration.class))
|
||||
.thenReturn(endpointConfig);
|
||||
|
||||
mockMvc.perform(get("/pdf-to-cbr")).andExpect(status().isNotFound());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return OK when endpoint enabled")
|
||||
void shouldReturnOkWhenEnabled() throws Exception {
|
||||
try (MockedStatic<ApplicationContextProvider> acp =
|
||||
org.mockito.Mockito.mockStatic(ApplicationContextProvider.class)) {
|
||||
EndpointConfiguration endpointConfig = mock(EndpointConfiguration.class);
|
||||
when(endpointConfig.isEndpointEnabled(eq("pdf-to-cbr"))).thenReturn(true);
|
||||
acp.when(() -> ApplicationContextProvider.getBean(EndpointConfiguration.class))
|
||||
.thenReturn(endpointConfig);
|
||||
|
||||
mockMvc.perform(get("/pdf-to-cbr"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(view().name("convert/pdf-to-cbr"))
|
||||
.andExpect(model().attribute("currentPage", "pdf-to-cbr"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("PDF to EPUB endpoint tests")
|
||||
class PdfToEpubTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return 404 when endpoint disabled")
|
||||
void shouldReturn404WhenDisabled() throws Exception {
|
||||
try (MockedStatic<ApplicationContextProvider> acp =
|
||||
org.mockito.Mockito.mockStatic(ApplicationContextProvider.class)) {
|
||||
EndpointConfiguration endpointConfig = mock(EndpointConfiguration.class);
|
||||
when(endpointConfig.isEndpointEnabled(eq("pdf-to-epub"))).thenReturn(false);
|
||||
acp.when(() -> ApplicationContextProvider.getBean(EndpointConfiguration.class))
|
||||
.thenReturn(endpointConfig);
|
||||
|
||||
mockMvc.perform(get("/pdf-to-epub")).andExpect(status().isNotFound());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should return OK when endpoint enabled")
|
||||
void shouldReturnOkWhenEnabled() throws Exception {
|
||||
try (MockedStatic<ApplicationContextProvider> acp =
|
||||
org.mockito.Mockito.mockStatic(ApplicationContextProvider.class)) {
|
||||
EndpointConfiguration endpointConfig = mock(EndpointConfiguration.class);
|
||||
when(endpointConfig.isEndpointEnabled(eq("pdf-to-epub"))).thenReturn(true);
|
||||
acp.when(() -> ApplicationContextProvider.getBean(EndpointConfiguration.class))
|
||||
.thenReturn(endpointConfig);
|
||||
|
||||
mockMvc.perform(get("/pdf-to-epub"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(view().name("convert/pdf-to-epub"))
|
||||
.andExpect(model().attribute("currentPage", "pdf-to-epub"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should handle pdf-to-img with default maxDPI=500")
|
||||
void shouldHandlePdfToImgWithDefaultMaxDpi() throws Exception {
|
||||
try (MockedStatic<ApplicationContextProvider> acp =
|
||||
org.mockito.Mockito.mockStatic(ApplicationContextProvider.class);
|
||||
MockedStatic<CheckProgramInstall> cpi =
|
||||
org.mockito.Mockito.mockStatic(CheckProgramInstall.class)) {
|
||||
cpi.when(CheckProgramInstall::isPythonAvailable).thenReturn(true);
|
||||
acp.when(() -> ApplicationContextProvider.getBean(ApplicationProperties.class))
|
||||
.thenReturn(null);
|
||||
|
||||
mockMvc.perform(get("/pdf-to-img"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(view().name("convert/pdf-to-img"))
|
||||
.andExpect(model().attribute("isPython", true))
|
||||
.andExpect(model().attribute("maxDPI", 500));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should handle pdf-to-video with default maxDPI=500")
|
||||
void shouldHandlePdfToVideoWithDefaultMaxDpi() throws Exception {
|
||||
try (MockedStatic<ApplicationContextProvider> acp =
|
||||
org.mockito.Mockito.mockStatic(ApplicationContextProvider.class)) {
|
||||
acp.when(() -> ApplicationContextProvider.getBean(ApplicationProperties.class))
|
||||
.thenReturn(null);
|
||||
|
||||
mockMvc.perform(get("/pdf-to-video"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(view().name("convert/pdf-to-video"))
|
||||
.andExpect(model().attribute("maxDPI", 500))
|
||||
.andExpect(model().attribute("currentPage", "pdf-to-video"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should handle pdf-to-img with configured maxDPI from properties")
|
||||
void shouldHandlePdfToImgWithConfiguredMaxDpi() throws Exception {
|
||||
// Covers the 'if' branch (properties and system not null)
|
||||
try (MockedStatic<ApplicationContextProvider> acp =
|
||||
org.mockito.Mockito.mockStatic(ApplicationContextProvider.class);
|
||||
MockedStatic<CheckProgramInstall> cpi =
|
||||
org.mockito.Mockito.mockStatic(CheckProgramInstall.class)) {
|
||||
|
||||
ApplicationProperties properties =
|
||||
org.mockito.Mockito.mock(
|
||||
ApplicationProperties.class, org.mockito.Mockito.RETURNS_DEEP_STUBS);
|
||||
when(properties.getSystem().getMaxDPI()).thenReturn(777);
|
||||
acp.when(() -> ApplicationContextProvider.getBean(ApplicationProperties.class))
|
||||
.thenReturn(properties);
|
||||
cpi.when(CheckProgramInstall::isPythonAvailable).thenReturn(true);
|
||||
|
||||
mockMvc.perform(get("/pdf-to-img"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(view().name("convert/pdf-to-img"))
|
||||
.andExpect(model().attribute("isPython", true))
|
||||
.andExpect(model().attribute("maxDPI", 777))
|
||||
.andExpect(model().attribute("currentPage", "pdf-to-img"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should handle pdf-to-video with configured maxDPI from properties")
|
||||
void shouldHandlePdfToVideoWithConfiguredMaxDpi() throws Exception {
|
||||
// Covers the 'if' branch (properties and system not null)
|
||||
try (MockedStatic<ApplicationContextProvider> acp =
|
||||
org.mockito.Mockito.mockStatic(ApplicationContextProvider.class)) {
|
||||
|
||||
ApplicationProperties properties =
|
||||
org.mockito.Mockito.mock(
|
||||
ApplicationProperties.class, org.mockito.Mockito.RETURNS_DEEP_STUBS);
|
||||
when(properties.getSystem().getMaxDPI()).thenReturn(640);
|
||||
acp.when(() -> ApplicationContextProvider.getBean(ApplicationProperties.class))
|
||||
.thenReturn(properties);
|
||||
|
||||
mockMvc.perform(get("/pdf-to-video"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(view().name("convert/pdf-to-video"))
|
||||
.andExpect(model().attribute("maxDPI", 640))
|
||||
.andExpect(model().attribute("currentPage", "pdf-to-video"));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user