From dd955b0fb0d8577434a98d207921d4ef401762c5 Mon Sep 17 00:00:00 2001 From: Sergey Grigoriev Date: Thu, 19 Dec 2024 10:45:15 +0100 Subject: [PATCH] feat: refactor the object model and cover with unit tests (#313) * feat: refactor the object model and covert with unit tests * feat: migration to generic 8.0.0 Refs: #312 #299 --- .mvn/maven.config | 2 +- README.md | 4 + pom.xml | 24 +- .../PdfExporterFormExtension.java | 5 +- .../converter/CoverPageProcessor.java | 2 +- .../pdf_exporter/converter/PdfConverter.java | 21 +- .../controller/ConverterApiController.java | 11 +- .../ConverterInternalController.java | 31 +- .../UtilityResourcesInternalController.java | 2 +- .../pdf_exporter/rest/model/DocumentData.java | 33 -- .../model/documents/DocumentBaseline.java | 45 +++ .../rest/model/documents/DocumentData.java | 44 ++ .../model/documents/ModelObjectProvider.java | 126 ++++++ .../documents/UniqueObjectConverter.java | 82 ++++ .../adapters/CommonUniqueObjectAdapter.java | 61 +++ .../adapters/IUniqueObjectAdapter.java | 35 ++ .../documents/adapters/LiveDocAdapter.java | 80 ++++ .../documents/adapters/LiveReportAdapter.java | 69 ++++ .../documents/adapters/TestRunAdapter.java | 63 +++ .../documents/adapters/WikiPageAdapter.java | 60 +++ .../rest/model/documents/id/DocumentId.java | 10 + .../model/documents/id/DocumentProject.java | 20 + .../rest/model/documents/id/LiveDocId.java | 33 ++ .../rest/model/documents/id/LiveReportId.java | 24 ++ .../rest/model/documents/id/TestRuntId.java | 23 ++ .../rest/model/documents/id/WikiPageId.java | 24 ++ .../service/PdfExporterPolarionService.java | 18 - .../service/PolarionBaselineExecutor.java | 32 ++ .../util/DocumentDataFactory.java | 33 ++ .../pdf_exporter/util/DocumentDataHelper.java | 282 ------------- .../util/DocumentFileNameHelper.java | 27 +- .../placeholder/PlaceholderProcessor.java | 25 +- .../util/velocity/VelocityEvaluator.java | 6 +- .../widgets/ExportToPdfButton.java | 1 - .../converter/CoverPageProcessorTest.java | 12 +- .../converter/PdfConverterTest.java | 75 ++-- .../model/documents/DocumentDataTest.java | 379 ++++++++++++++++++ .../documents/ModelObjectProviderTest.java | 277 +++++++++++++ .../documents/UniqueObjectConverterTest.java | 48 +++ .../LiveDocGetRevisionPlaceholderTest.java | 38 ++ .../PdfExporterPolarionServiceTest.java | 42 -- .../service/PolarionBaselineExecutorTest.java | 38 ++ .../DocumentDataFactoryMockExtension.java | 51 +++ .../util/CustomResourceUrlResolverTest.java | 6 +- .../util/DocumentDataFactoryTest.java | 109 +++++ .../util/DocumentDataHelperTest.java | 68 ---- .../util/DocumentFileNameHelperTest.java | 75 +++- .../pdf_exporter/util/WildcardUtilsTest.java | 2 +- .../PdfConverterWeasyPrintTest.java | 60 +-- .../BulkPdfExportWidgetRendererTest.java | 4 +- 50 files changed, 2012 insertions(+), 630 deletions(-) delete mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/DocumentData.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentBaseline.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentData.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/ModelObjectProvider.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/UniqueObjectConverter.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/CommonUniqueObjectAdapter.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/IUniqueObjectAdapter.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveDocAdapter.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveReportAdapter.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/TestRunAdapter.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/WikiPageAdapter.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/DocumentId.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/DocumentProject.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/LiveDocId.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/LiveReportId.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/TestRuntId.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/WikiPageId.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/service/PolarionBaselineExecutor.java create mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataFactory.java delete mode 100644 src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataHelper.java create mode 100644 src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentDataTest.java create mode 100644 src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/ModelObjectProviderTest.java create mode 100644 src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/UniqueObjectConverterTest.java create mode 100644 src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveDocGetRevisionPlaceholderTest.java create mode 100644 src/test/java/ch/sbb/polarion/extension/pdf_exporter/service/PolarionBaselineExecutorTest.java create mode 100644 src/test/java/ch/sbb/polarion/extension/pdf_exporter/test_extensions/DocumentDataFactoryMockExtension.java create mode 100644 src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataFactoryTest.java delete mode 100644 src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataHelperTest.java diff --git a/.mvn/maven.config b/.mvn/maven.config index 51aef676..8844d78b 100644 --- a/.mvn/maven.config +++ b/.mvn/maven.config @@ -1 +1 @@ --P polarion2404 +-P polarion2410 diff --git a/README.md b/README.md index 0e88ae16..041b78dd 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,10 @@ All good so far. ## Upgrade +### Upgrade from version 7.x.x to 8.0.0 + +In version 8.0.0 support for Polarion 2404 and older has been dropped. This extensions supports only Polarion 2410. + ### Upgrade from version 6.x.x to 7.0.0 In version 7.0.0 `/export-filename` REST API endpoint changed. As a result, if the endpoint has been used, it's required to adjust the calls accordingly. diff --git a/pom.xml b/pom.xml index 3fd4e058..ca4b1356 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ ch.sbb.polarion.extensions ch.sbb.polarion.extension.generic - 7.7.0 + 8.0.0 ch.sbb.polarion.extension.pdf-exporter @@ -76,27 +76,12 @@ - + - polarion2404 + polarion2410 true - - velocity-engine-core-2.3 - - - - - - polarion2310 - - velocity-engine-core-2.3 - - - - - polarion2410 org.apache.velocity.engine-core_2.3.0 @@ -263,7 +248,8 @@ JSON - ch.sbb.polarion.extension.generic.rest.controller + ch.sbb.polarion.extension.generic.rest.controller.info + ch.sbb.polarion.extension.generic.rest.controller.settings ch.sbb.polarion.extension.generic.rest.model ch.sbb.polarion.extension.pdf_exporter.rest.controller ch.sbb.polarion.extension.pdf_exporter.rest.model diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/PdfExporterFormExtension.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/PdfExporterFormExtension.java index 460c7575..463f143e 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/PdfExporterFormExtension.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/PdfExporterFormExtension.java @@ -11,6 +11,7 @@ import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.localization.Language; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.stylepackage.StylePackageModel; import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; +import ch.sbb.polarion.extension.pdf_exporter.service.PolarionBaselineExecutor; import ch.sbb.polarion.extension.pdf_exporter.settings.CoverPageSettings; import ch.sbb.polarion.extension.pdf_exporter.settings.CssSettings; import ch.sbb.polarion.extension.pdf_exporter.settings.HeaderFooterSettings; @@ -57,7 +58,7 @@ public class PdfExporterFormExtension implements IFormExtension { public String render(@NotNull IFormExtensionContext context) { return TransactionalExecutor.executeSafelyInReadOnlyTransaction(transaction -> { String baselineRevision = transaction.context().baselineRevision(); - return polarionService.executeInBaseline(baselineRevision, transaction, () -> renderForm(transaction.context(), context.object().getOldApi())); + return PolarionBaselineExecutor.executeInBaseline(baselineRevision, transaction, () -> renderForm(transaction.context(), context.object().getOldApi())); }); } @@ -320,7 +321,7 @@ private String adjustButtons(@NotNull String form, @NotNull IModule module, @Not } private String getFilename(@NotNull IModule module) { - DocumentFileNameHelper documentFileNameHelper = new DocumentFileNameHelper(new PdfExporterPolarionService()); + DocumentFileNameHelper documentFileNameHelper = new DocumentFileNameHelper(); ExportParams exportParams = ExportParams.builder() .projectId(module.getProject().getId()) diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/converter/CoverPageProcessor.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/converter/CoverPageProcessor.java index 66bd9df6..85707c58 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/converter/CoverPageProcessor.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/converter/CoverPageProcessor.java @@ -1,8 +1,8 @@ package ch.sbb.polarion.extension.pdf_exporter.converter; import ch.sbb.polarion.extension.generic.settings.SettingId; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.coverpage.CoverPageModel; import ch.sbb.polarion.extension.pdf_exporter.settings.CoverPageSettings; import ch.sbb.polarion.extension.pdf_exporter.util.MediaUtils; diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/converter/PdfConverter.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/converter/PdfConverter.java index 9105d366..6d77b715 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/converter/PdfConverter.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/converter/PdfConverter.java @@ -4,11 +4,11 @@ import ch.sbb.polarion.extension.generic.settings.SettingId; import ch.sbb.polarion.extension.generic.util.ScopeUtils; import ch.sbb.polarion.extension.pdf_exporter.properties.PdfExporterExtensionConfiguration; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.ExportMetaInfoCallback; import ch.sbb.polarion.extension.pdf_exporter.rest.model.WorkItemRefData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.headerfooter.HeaderFooterModel; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.webhooks.AuthType; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.webhooks.WebhookConfig; @@ -18,7 +18,7 @@ import ch.sbb.polarion.extension.pdf_exporter.settings.HeaderFooterSettings; import ch.sbb.polarion.extension.pdf_exporter.settings.LocalizationSettings; import ch.sbb.polarion.extension.pdf_exporter.settings.WebhooksSettings; -import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataHelper; +import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataFactory; import ch.sbb.polarion.extension.pdf_exporter.util.EnumValuesProvider; import ch.sbb.polarion.extension.pdf_exporter.util.HtmlLogger; import ch.sbb.polarion.extension.pdf_exporter.util.HtmlProcessor; @@ -59,7 +59,6 @@ import java.util.Base64; import java.util.Collections; import java.util.List; -import java.util.Objects; @AllArgsConstructor @SuppressWarnings("java:S1200") @@ -70,7 +69,6 @@ public class PdfConverter { private final HeaderFooterSettings headerFooterSettings; private final CssSettings cssSettings; - private final DocumentDataHelper documentDataHelper; private final PlaceholderProcessor placeholderProcessor; private final VelocityEvaluator velocityEvaluator; private final CoverPageProcessor coverPageProcessor; @@ -82,7 +80,6 @@ public PdfConverter() { pdfExporterPolarionService = new PdfExporterPolarionService(); headerFooterSettings = new HeaderFooterSettings(); cssSettings = new CssSettings(); - documentDataHelper = new DocumentDataHelper(pdfExporterPolarionService); placeholderProcessor = new PlaceholderProcessor(); velocityEvaluator = new VelocityEvaluator(); coverPageProcessor = new CoverPageProcessor(); @@ -99,7 +96,7 @@ public byte[] convertToPdf(@NotNull ExportParams exportParams, @Nullable ExportM generationLog.log("Starting html generation"); @Nullable ITrackerProject project = getTrackerProject(exportParams); - @NotNull final DocumentData documentData = getDocumentData(exportParams, project); + @NotNull final DocumentData documentData = DocumentDataFactory.getDocumentData(exportParams, true); @NotNull String htmlContent = prepareHtmlContent(exportParams, project, documentData, metaInfoCallback); generationLog.log("Html is ready, starting pdf generation"); @@ -118,7 +115,7 @@ public byte[] convertToPdf(@NotNull ExportParams exportParams, @Nullable ExportM public @NotNull String prepareHtmlContent(@NotNull ExportParams exportParams, @Nullable ExportMetaInfoCallback metaInfoCallback) { @Nullable ITrackerProject project = getTrackerProject(exportParams); - @NotNull final DocumentData documentData = getDocumentData(exportParams, project); + @NotNull final DocumentData documentData = DocumentDataFactory.getDocumentData(exportParams, true); return prepareHtmlContent(exportParams, project, documentData, metaInfoCallback); } @@ -130,16 +127,6 @@ public byte[] convertToPdf(@NotNull ExportParams exportParams, @Nullable ExportM return project; } - private @NotNull DocumentData getDocumentData(@NotNull ExportParams exportParams, @Nullable ITrackerProject project) { - return switch (exportParams.getDocumentType()) { - case LIVE_DOC -> documentDataHelper.getLiveDoc(Objects.requireNonNull(project), exportParams); - case LIVE_REPORT -> documentDataHelper.getLiveReport(project, exportParams); - case TEST_RUN -> documentDataHelper.getTestRun(Objects.requireNonNull(project), exportParams); - case WIKI_PAGE -> documentDataHelper.getWikiPage(project, exportParams); - case BASELINE_COLLECTION -> throw new IllegalArgumentException("Unsupported document type: %s".formatted(exportParams.getDocumentType())); - }; - } - private @NotNull String prepareHtmlContent(@NotNull ExportParams exportParams, @Nullable ITrackerProject project, @NotNull DocumentData documentData, @Nullable ExportMetaInfoCallback metaInfoCallback) { String cssContent = getCssContent(documentData, exportParams); String preparedDocumentContent = postProcessDocumentContent(exportParams, project, documentData.getContent()); diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/ConverterApiController.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/ConverterApiController.java index ae045e1b..61184a32 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/ConverterApiController.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/ConverterApiController.java @@ -11,7 +11,6 @@ import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.Orientation; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.PaperSize; import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; -import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataHelper; import ch.sbb.polarion.extension.pdf_exporter.util.PdfValidationService; import org.jetbrains.annotations.VisibleForTesting; import org.springframework.web.context.request.RequestAttributes; @@ -33,14 +32,8 @@ public ConverterApiController() { @VisibleForTesting @SuppressWarnings("squid:S5803") - ConverterApiController(PdfExporterPolarionService pdfExporterPolarionService, - PdfConverter pdfConverter, - PdfValidationService pdfValidationService, - DocumentDataHelper documentDataHelper, - PdfConverterJobsService pdfConverterJobService, - UriInfo uriInfo, - HtmlToPdfConverter htmlToPdfConverter) { - super(pdfExporterPolarionService, pdfConverter, pdfValidationService, documentDataHelper, pdfConverterJobService, uriInfo, htmlToPdfConverter); + ConverterApiController(PdfExporterPolarionService pdfExporterPolarionService, PdfConverter pdfConverter, PdfValidationService pdfValidationService, PdfConverterJobsService pdfConverterJobService, UriInfo uriInfo, HtmlToPdfConverter htmlToPdfConverter) { + super(pdfConverter, pdfValidationService, pdfConverterJobService, uriInfo, htmlToPdfConverter); this.polarionService = pdfExporterPolarionService; } diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/ConverterInternalController.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/ConverterInternalController.java index cf5e5d73..8e2f2bd1 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/ConverterInternalController.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/ConverterInternalController.java @@ -11,12 +11,14 @@ import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.Orientation; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.PaperSize; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.jobs.ConverterJobDetails; import ch.sbb.polarion.extension.pdf_exporter.rest.model.jobs.ConverterJobStatus; -import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; -import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataHelper; +import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataFactory; import ch.sbb.polarion.extension.pdf_exporter.util.DocumentFileNameHelper; +import ch.sbb.polarion.extension.pdf_exporter.util.NumberedListsSanitizer; import ch.sbb.polarion.extension.pdf_exporter.util.PdfValidationService; +import com.polarion.alm.tracker.model.IModule; import com.polarion.core.util.StringUtils; import com.polarion.platform.core.PlatformContext; import com.polarion.platform.security.ISecurityService; @@ -29,6 +31,7 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; import org.springframework.http.HttpStatus; @@ -49,6 +52,7 @@ import javax.ws.rs.core.UriInfo; import java.net.URI; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -60,10 +64,8 @@ public class ConverterInternalController { private static final String EXPORT_FILENAME_HEADER = "Export-Filename"; - private final PdfExporterPolarionService pdfExporterPolarionService; private final PdfConverter pdfConverter; private final PdfValidationService pdfValidationService; - private final DocumentDataHelper documentDataHelper; private final PdfConverterJobsService pdfConverterJobService; private final PropertiesUtility propertiesUtility; private final HtmlToPdfConverter htmlToPdfConverter; @@ -72,10 +74,8 @@ public class ConverterInternalController { private UriInfo uriInfo; public ConverterInternalController() { - this.pdfExporterPolarionService = new PdfExporterPolarionService(); this.pdfConverter = new PdfConverter(); this.pdfValidationService = new PdfValidationService(pdfConverter); - this.documentDataHelper = new DocumentDataHelper(pdfExporterPolarionService); ISecurityService securityService = PlatformContext.getPlatform().lookupService(ISecurityService.class); this.pdfConverterJobService = new PdfConverterJobsService(pdfConverter, securityService); this.propertiesUtility = new PropertiesUtility(); @@ -83,17 +83,9 @@ public ConverterInternalController() { } @VisibleForTesting - ConverterInternalController(PdfExporterPolarionService pdfExporterPolarionService, - PdfConverter pdfConverter, - PdfValidationService pdfValidationService, - DocumentDataHelper documentDataHelper, - PdfConverterJobsService pdfConverterJobService, - UriInfo uriInfo, - HtmlToPdfConverter htmlToPdfConverter) { - this.pdfExporterPolarionService = pdfExporterPolarionService; + ConverterInternalController(PdfConverter pdfConverter, PdfValidationService pdfValidationService, PdfConverterJobsService pdfConverterJobService, UriInfo uriInfo, HtmlToPdfConverter htmlToPdfConverter) { this.pdfConverter = pdfConverter; this.pdfValidationService = pdfValidationService; - this.documentDataHelper = documentDataHelper; this.pdfConverterJobService = pdfConverterJobService; this.uriInfo = uriInfo; this.propertiesUtility = new PropertiesUtility(); @@ -364,7 +356,10 @@ public WidthValidationResult validatePdfWidth( ) @SuppressWarnings("java:S1166") public NestedListsCheck checkNestedLists(ExportParams exportParams) { - boolean containsNestedLists = documentDataHelper.hasLiveDocNestedNumberedLists(exportParams); + DocumentData documentData = DocumentDataFactory.getDocumentData(exportParams, true); + @NotNull String content = Objects.requireNonNull(documentData.getContent()); + boolean containsNestedLists = new NumberedListsSanitizer().containsNestedNumberedLists(content); + return NestedListsCheck.builder().containsNestedLists(containsNestedLists).build(); } @@ -386,8 +381,8 @@ private void validateExportParameters(ExportParams exportParams) { private String getFileName(@Nullable ExportParams exportParams) { if (exportParams != null) { return StringUtils.isEmpty(exportParams.getFileName()) - ? new DocumentFileNameHelper(pdfExporterPolarionService).getDocumentFileName(exportParams) - : exportParams.getFileName(); + ? new DocumentFileNameHelper().getDocumentFileName(exportParams) + : exportParams.getFileName(); } else { return "document.pdf"; } diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/UtilityResourcesInternalController.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/UtilityResourcesInternalController.java index 6c28fe8b..613eeadf 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/UtilityResourcesInternalController.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/controller/UtilityResourcesInternalController.java @@ -109,7 +109,7 @@ public String getProjectName(@PathParam("projectId") String projectId) { } ) public String getFileName(ExportParams exportParams) { - return new DocumentFileNameHelper(pdfExporterPolarionService).getDocumentFileName(exportParams); + return new DocumentFileNameHelper().getDocumentFileName(exportParams); } @GET diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/DocumentData.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/DocumentData.java deleted file mode 100644 index 111cd0a8..00000000 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/DocumentData.java +++ /dev/null @@ -1,33 +0,0 @@ -package ch.sbb.polarion.extension.pdf_exporter.rest.model; - -import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; -import com.polarion.alm.projects.model.IUniqueObject; -import lombok.Builder; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -@Builder(builderMethodName = "create") -@Getter -public class DocumentData { - private final @NotNull DocumentType documentType; - private final @NotNull T documentObject; - - private @NotNull String id; - private @NotNull String title; - private @Nullable String content; - - private @Nullable String projectName; - private @Nullable String lastRevision; - private @Nullable String baselineName; - - public static DocumentDataBuilder builder(@NotNull DocumentType documentType, @NotNull T documentObject) { - return DocumentData.create() - .documentType(documentType) - .documentObject(documentObject); - } - - // making javadoc maven plugin happy - @SuppressWarnings("unused") - public static class DocumentDataBuilder {} -} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentBaseline.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentBaseline.java new file mode 100644 index 00000000..fe7f3e59 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentBaseline.java @@ -0,0 +1,45 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents; + +import com.polarion.alm.tracker.model.IBaseline; +import lombok.Data; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class DocumentBaseline { + private final @Nullable String projectBaselineName; + private final @Nullable String documentBaselineName; + + public DocumentBaseline(@Nullable String projectBaselineName, @Nullable String documentBaselineName) { + this.projectBaselineName = projectBaselineName; + this.documentBaselineName = documentBaselineName; + } + + public String asPlaceholder() { + List names = new ArrayList<>(); + + if (projectBaselineName != null) { + names.add("pb. " + projectBaselineName); + } + + if (documentBaselineName != null) { + names.add("db. " + documentBaselineName); + } + + return String.join(" | ", names); + } + + public static @NotNull DocumentBaseline from(@Nullable IBaseline projectBaseline, @Nullable IBaseline moduleBaseline) { + String projectBaselineName = projectBaseline != null ? projectBaseline.getName() : null; + String documentBaselineName = moduleBaseline != null ? moduleBaseline.getName() : null; + return new DocumentBaseline(projectBaselineName, documentBaselineName); + } + + public static @NotNull DocumentBaseline empty() { + return new DocumentBaseline(null, null); + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentData.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentData.java new file mode 100644 index 00000000..b9923889 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentData.java @@ -0,0 +1,44 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentId; +import com.polarion.alm.projects.model.IUniqueObject; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Builder +@Getter +public class DocumentData { + @Setter(AccessLevel.NONE) + private final @NotNull T documentObject; + + @Setter(AccessLevel.NONE) + private final @NotNull DocumentId id; + @Setter(AccessLevel.NONE) + private final @NotNull DocumentType type; + @Setter(AccessLevel.NONE) + private final @NotNull String title; + + private final @Nullable String content; + + private final @Nullable DocumentBaseline baseline; + private final @Nullable String revision; + private final @NotNull String lastRevision; + private final @NotNull String revisionPlaceholder; + + public static DocumentDataBuilder creator(@NotNull DocumentType documentType, @NotNull T documentObject) { + return DocumentData.builder() + .type(documentType) + .documentObject(documentObject); + } + + // making javadoc maven plugin happy + @SuppressWarnings("unused") + public static class DocumentDataBuilder {} +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/ModelObjectProvider.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/ModelObjectProvider.java new file mode 100644 index 00000000..b88afa08 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/ModelObjectProvider.java @@ -0,0 +1,126 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; +import com.polarion.alm.projects.model.IProject; +import com.polarion.alm.shared.api.model.ModelObject; +import com.polarion.alm.shared.api.model.document.Document; +import com.polarion.alm.shared.api.model.document.DocumentReference; +import com.polarion.alm.shared.api.model.rp.RichPage; +import com.polarion.alm.shared.api.model.rp.RichPageReference; +import com.polarion.alm.shared.api.model.tr.TestRun; +import com.polarion.alm.shared.api.model.tr.TestRunReference; +import com.polarion.alm.shared.api.model.wiki.WikiPage; +import com.polarion.alm.shared.api.model.wiki.WikiPageReference; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import com.polarion.core.util.StringUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.Optional; + +public class ModelObjectProvider { + public static final String URL_QUERY_PARAM_ID = "id"; + + private static final String LOCATION_PATH_IS_REQUIRED_FOR_EXPORT = "Location path is required for export"; + private static final String PROJECT_ID_IS_REQUIRED_FOR_EXPORT = "Project id is required for export"; + private static final String TEST_RUN_ID_IS_REQUIRED_FOR_EXPORT = "Test run id is required for export"; + + private final @NotNull ExportParams exportParams; + private final @NotNull PdfExporterPolarionService pdfExporterPolarionService; + + public ModelObjectProvider(@NotNull ExportParams exportParams) { + this.exportParams = exportParams; + this.pdfExporterPolarionService = new PdfExporterPolarionService(); + } + + public ModelObjectProvider(@NotNull ExportParams exportParams, @NotNull PdfExporterPolarionService pdfExporterPolarionService) { + this.exportParams = exportParams; + this.pdfExporterPolarionService = pdfExporterPolarionService; + } + + public ModelObject getModelObject(ReadOnlyTransaction transaction) { + return switch (exportParams.getDocumentType()) { + case LIVE_DOC -> getDocument(transaction); + case LIVE_REPORT -> getRichPage(transaction); + case TEST_RUN -> getTestRun(transaction); + case WIKI_PAGE -> getWikiPage(transaction); + case BASELINE_COLLECTION -> throw new IllegalArgumentException("Unsupported document type: %s".formatted(exportParams.getDocumentType())); + }; + } + + public @NotNull RichPage getRichPage(@NotNull ReadOnlyTransaction transaction) { + String projectId = getProjectId().orElse(""); + String locationPath = getLocationPath().orElseThrow(() -> new IllegalArgumentException(LOCATION_PATH_IS_REQUIRED_FOR_EXPORT)); + + RichPageReference richPageReference = RichPageReference.fromPath(createPath(projectId, locationPath)); + if (exportParams.getRevision() != null) { + richPageReference = richPageReference.getWithRevision(exportParams.getRevision()); + } + + return richPageReference.getOriginal(transaction); + } + + public @NotNull TestRun getTestRun(ReadOnlyTransaction transaction) { + String projectId = getProjectId().orElseThrow(() -> new IllegalArgumentException(PROJECT_ID_IS_REQUIRED_FOR_EXPORT)); + String testRunId = getTestRunId().orElseThrow(() -> new IllegalArgumentException(TEST_RUN_ID_IS_REQUIRED_FOR_EXPORT)); + + TestRunReference testRunReference = TestRunReference.fromPath(createPath(projectId, testRunId)); + if (exportParams.getRevision() != null) { + testRunReference = testRunReference.getWithRevision(exportParams.getRevision()); + } + + return testRunReference.getOriginal(transaction); + } + + public @NotNull WikiPage getWikiPage(@NotNull ReadOnlyTransaction transaction) { + String projectId = getProjectId().orElse(""); + String locationPath = getLocationPath().orElseThrow(() -> new IllegalArgumentException(LOCATION_PATH_IS_REQUIRED_FOR_EXPORT)); + + WikiPageReference wikiPageReference = WikiPageReference.fromPath(createPath(projectId, locationPath)); + if (exportParams.getRevision() != null) { + wikiPageReference = wikiPageReference.getWithRevision(exportParams.getRevision()); + } + + return wikiPageReference.getOriginal(transaction); + } + + public Document getDocument(ReadOnlyTransaction transaction) { + String projectId = getProjectId().orElseThrow(() -> new IllegalArgumentException(PROJECT_ID_IS_REQUIRED_FOR_EXPORT)); + String locationPath = getLocationPath().orElseThrow(() -> new IllegalArgumentException(LOCATION_PATH_IS_REQUIRED_FOR_EXPORT)); + + DocumentReference documentReference = DocumentReference.fromPath(createPath(projectId, locationPath)); + if (exportParams.getRevision() != null) { + documentReference = documentReference.getWithRevision(exportParams.getRevision()); + } + + return documentReference.getOriginal(transaction); + } + + + private Optional getProjectId() { + IProject project = null; + if (!StringUtils.isEmpty(exportParams.getProjectId())) { + project = pdfExporterPolarionService.getProject(exportParams.getProjectId()); + } + String projectId = project != null ? project.getId() : null; + return Optional.ofNullable(projectId); + } + + private Optional getLocationPath() { + return Optional.ofNullable(exportParams.getLocationPath()); + } + + private Optional getTestRunId() { + Map urlQueryParameters = exportParams.getUrlQueryParameters(); + if (urlQueryParameters == null || !urlQueryParameters.containsKey(URL_QUERY_PARAM_ID)) { + return Optional.empty(); + } + return Optional.ofNullable(urlQueryParameters.get(URL_QUERY_PARAM_ID)); + } + + public static @NotNull String createPath(@NotNull String projectId, @NotNull String locationPath) { + return String.format("%s/%s", projectId, locationPath); + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/UniqueObjectConverter.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/UniqueObjectConverter.java new file mode 100644 index 00000000..6b8f3e0c --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/UniqueObjectConverter.java @@ -0,0 +1,82 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters.IUniqueObjectAdapter; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters.LiveDocAdapter; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters.LiveReportAdapter; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters.TestRunAdapter; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters.WikiPageAdapter; +import ch.sbb.polarion.extension.pdf_exporter.service.PolarionBaselineExecutor; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.shared.api.model.ModelObject; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import com.polarion.alm.shared.api.transaction.TransactionalExecutor; +import com.polarion.alm.tracker.model.IModule; +import com.polarion.alm.tracker.model.IRichPage; +import com.polarion.alm.tracker.model.ITestRun; +import com.polarion.alm.tracker.model.IWikiPage; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public class UniqueObjectConverter { + + @Getter + private final @NotNull IUniqueObjectAdapter uniqueObjectAdapter; + private boolean withContent; + private @Nullable ExportParams exportParams; + + public UniqueObjectConverter(@NotNull IUniqueObject uniqueObject) { + if (uniqueObject instanceof IModule module) { + uniqueObjectAdapter = new LiveDocAdapter(module); + } else if (uniqueObject instanceof IRichPage richPage) { + uniqueObjectAdapter = new LiveReportAdapter(richPage); + } else if (uniqueObject instanceof IWikiPage wikiPage) { + uniqueObjectAdapter = new WikiPageAdapter(wikiPage); + } else if (uniqueObject instanceof ITestRun testRun) { + uniqueObjectAdapter = new TestRunAdapter(testRun); + } else { + throw new IllegalArgumentException("Unsupported unique object type: " + uniqueObject.getClass()); + } + } + + public UniqueObjectConverter(@NotNull ModelObject modelObject) { + this((IUniqueObject) modelObject.getOldApi()); + } + + public UniqueObjectConverter withExportParams(ExportParams exportParams) { + this.exportParams = exportParams; + return this; + } + + public UniqueObjectConverter withContent(boolean withContent) { + this.withContent = withContent; + return this; + } + + public @NotNull DocumentData toDocumentData() { + return Objects.requireNonNull(TransactionalExecutor.executeSafelyInReadOnlyTransaction(this::toDocumentData)); + } + + public @NotNull DocumentData toDocumentData(@NotNull ReadOnlyTransaction transaction) { + String baselineRevision = getBaselineRevision(); + return PolarionBaselineExecutor.executeInBaseline(baselineRevision, transaction, () -> DocumentData.builder() + .documentObject(uniqueObjectAdapter.getUniqueObject()) + .id(uniqueObjectAdapter.getDocumentId()) + .type(uniqueObjectAdapter.getDocumentType()) + .title(uniqueObjectAdapter.getTitle()) + .revision(uniqueObjectAdapter.getRevision()) + .lastRevision(uniqueObjectAdapter.getLastRevision()) + .revisionPlaceholder(uniqueObjectAdapter.getRevisionPlaceholder()) + .baseline(uniqueObjectAdapter.getDocumentBaseline(transaction)) + .content(withContent && exportParams != null ? uniqueObjectAdapter.getContent(exportParams, transaction) : null) + .build()); + } + + private @Nullable String getBaselineRevision() { + return exportParams != null ? exportParams.getBaselineRevision() : null; + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/CommonUniqueObjectAdapter.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/CommonUniqueObjectAdapter.java new file mode 100644 index 00000000..7340d74d --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/CommonUniqueObjectAdapter.java @@ -0,0 +1,61 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentBaseline; +import com.polarion.alm.projects.model.IProject; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import com.polarion.alm.shared.api.transaction.TransactionalExecutor; +import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; +import com.polarion.alm.tracker.ITrackerService; +import com.polarion.alm.tracker.model.IBaseline; +import com.polarion.alm.tracker.model.ipi.IInternalBaselinesManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public abstract class CommonUniqueObjectAdapter implements IUniqueObjectAdapter { + + @Override + public @Nullable String getRevision() { + return getUniqueObject().getRevision(); + } + + @Override + public @NotNull String getLastRevision() { + return getUniqueObject().getLastRevision(); + } + + @Override + public @NotNull String getRevisionPlaceholder() { + return getRevision() != null ? getRevision() : getLastRevision(); + } + + @Override + public @NotNull String getContent(@NotNull ExportParams exportParams) { + return Objects.requireNonNull(TransactionalExecutor.executeSafelyInReadOnlyTransaction(transaction -> getContent(exportParams, transaction))); + } + + @Override + public @NotNull DocumentBaseline getDocumentBaseline() { + return Objects.requireNonNull(TransactionalExecutor.executeSafelyInReadOnlyTransaction(this::getDocumentBaseline)); + } + + @Override + public @NotNull DocumentBaseline getDocumentBaseline(@NotNull ReadOnlyTransaction transaction) { + IProject project = getUniqueObject().getProject(); + if (project != null) { + String revision = getRevision() != null ? getRevision() : getLastRevision(); + + ITrackerService trackerService = ((InternalReadOnlyTransaction) transaction).services().trackerService(); + IInternalBaselinesManager baselinesManager = (IInternalBaselinesManager) trackerService.getTrackerProject(project).getBaselinesManager(); + IBaseline projectBaseline = baselinesManager.getRevisionBaseline(revision); + IBaseline moduleBaseline = baselinesManager.getRevisionBaseline(getUniqueObject(), revision); + + return DocumentBaseline.from(projectBaseline, moduleBaseline); + } else { + return DocumentBaseline.empty(); + } + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/IUniqueObjectAdapter.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/IUniqueObjectAdapter.java new file mode 100644 index 00000000..1fc194ba --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/IUniqueObjectAdapter.java @@ -0,0 +1,35 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentBaseline; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentId; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface IUniqueObjectAdapter { + + @NotNull T getUniqueObject(); + + @NotNull DocumentId getDocumentId(); + + @NotNull DocumentType getDocumentType(); + + @NotNull String getTitle(); + + @Nullable String getRevision(); + + @NotNull String getLastRevision(); + + @NotNull String getRevisionPlaceholder(); + + @NotNull String getContent(@NotNull ExportParams exportParams); + + @NotNull String getContent(@NotNull ExportParams exportParams, @NotNull ReadOnlyTransaction transaction); + + @NotNull DocumentBaseline getDocumentBaseline(); + + @NotNull DocumentBaseline getDocumentBaseline(@NotNull ReadOnlyTransaction transaction); +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveDocAdapter.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveDocAdapter.java new file mode 100644 index 00000000..c109c5b5 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveDocAdapter.java @@ -0,0 +1,80 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentId; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentProject; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveDocId; +import ch.sbb.polarion.extension.pdf_exporter.service.PolarionBaselineExecutor; +import ch.sbb.polarion.extension.pdf_exporter.util.LiveDocCommentsProcessor; +import ch.sbb.polarion.extension.pdf_exporter.util.exporter.ModifiedDocumentRenderer; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.server.api.model.document.ProxyDocument; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; +import com.polarion.alm.shared.api.utils.html.RichTextRenderTarget; +import com.polarion.alm.shared.dle.document.DocumentRendererParameters; +import com.polarion.alm.tracker.model.IModule; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public class LiveDocAdapter extends CommonUniqueObjectAdapter { + public static final String DOC_REVISION_CUSTOM_FIELD = "docRevision"; + public static final String URL_QUERY_PARAM_LANGUAGE = "language"; + + private final @NotNull IModule module; + + public LiveDocAdapter(@NotNull IModule module) { + this.module = module; + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull T getUniqueObject() { + return (T) module; + } + + @Override + public @NotNull DocumentId getDocumentId() { + return new LiveDocId(getDocumentProject(), module.getModuleFolder(), module.getId()); + } + + private @NotNull DocumentProject getDocumentProject() { + return new DocumentProject(module.getProject()); + } + + @Override + public @NotNull DocumentType getDocumentType() { + return DocumentType.LIVE_DOC; + } + + @Override + public @NotNull String getTitle() { + return module.getTitleOrName(); + } + + @Override + public @NotNull String getRevisionPlaceholder() { + Object docRevision = module.getCustomField(DOC_REVISION_CUSTOM_FIELD); + return docRevision != null ? docRevision.toString() : super.getRevisionPlaceholder(); + } + + @Override + public @NotNull String getContent(@NotNull ExportParams exportParams, @NotNull ReadOnlyTransaction transaction) { + return PolarionBaselineExecutor.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { + ProxyDocument document = new ProxyDocument(module, (InternalReadOnlyTransaction) transaction); + + String internalContent = exportParams.getInternalContent() != null ? exportParams.getInternalContent() : document.getHomePageContentHtml(); + if (internalContent != null && exportParams.isEnableCommentsRendering()) { + // Add inline comments into document content + internalContent = new LiveDocCommentsProcessor().addLiveDocComments(document, internalContent); + } + Map documentParameters = exportParams.getUrlQueryParameters() == null ? Map.of() : exportParams.getUrlQueryParameters(); + DocumentRendererParameters parameters = new DocumentRendererParameters(null, documentParameters.get(URL_QUERY_PARAM_LANGUAGE)); + ModifiedDocumentRenderer documentRenderer = new ModifiedDocumentRenderer((InternalReadOnlyTransaction) transaction, document, RichTextRenderTarget.PDF_EXPORT, parameters); + return documentRenderer.render(internalContent != null ? internalContent : ""); + }); + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveReportAdapter.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveReportAdapter.java new file mode 100644 index 00000000..082690bd --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveReportAdapter.java @@ -0,0 +1,69 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentId; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentProject; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveReportId; +import ch.sbb.polarion.extension.pdf_exporter.service.PolarionBaselineExecutor; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.server.api.model.rp.ProxyRichPage; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; +import com.polarion.alm.shared.api.utils.collections.StrictMap; +import com.polarion.alm.shared.api.utils.collections.StrictMapImpl; +import com.polarion.alm.shared.api.utils.html.RichTextRenderTarget; +import com.polarion.alm.shared.rpe.RpeModelAspect; +import com.polarion.alm.shared.rpe.RpeRenderer; +import com.polarion.alm.tracker.model.IRichPage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class LiveReportAdapter extends CommonUniqueObjectAdapter { + private final @NotNull IRichPage richPage; + + public LiveReportAdapter(@NotNull IRichPage richPage) { + this.richPage = richPage; + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull T getUniqueObject() { + return (T) richPage; + } + + @Override + public @NotNull DocumentId getDocumentId() { + return new LiveReportId(getDocumentProject(), richPage.getId()); + } + + private @Nullable DocumentProject getDocumentProject() { + return richPage.getProject() == null ? null : new DocumentProject(richPage.getProject()); + } + + @Override + public @NotNull DocumentType getDocumentType() { + return DocumentType.LIVE_REPORT; + } + + @Override + public @NotNull String getTitle() { + return richPage.getTitleOrName(); + } + + @Override + public @NotNull String getContent(@NotNull ExportParams exportParams, @NotNull ReadOnlyTransaction transaction) { + return PolarionBaselineExecutor.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { + ProxyRichPage proxyRichPage = new ProxyRichPage(richPage, (InternalReadOnlyTransaction) transaction); + + String html = RpeModelAspect.getPageHtml(proxyRichPage); + Map liveReportParameters = exportParams.getUrlQueryParameters() == null ? Map.of() : exportParams.getUrlQueryParameters(); + StrictMap urlParameters = new StrictMapImpl<>(liveReportParameters); + RpeRenderer richPageRenderer = new RpeRenderer((InternalReadOnlyTransaction) transaction, html, RichTextRenderTarget.PDF_EXPORT, proxyRichPage.getReference(), proxyRichPage.getReference().scope(), urlParameters); + return richPageRenderer.render(null); + }); + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/TestRunAdapter.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/TestRunAdapter.java new file mode 100644 index 00000000..941dbd5b --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/TestRunAdapter.java @@ -0,0 +1,63 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentId; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentProject; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.TestRuntId; +import ch.sbb.polarion.extension.pdf_exporter.service.PolarionBaselineExecutor; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.server.api.model.tr.ProxyTestRun; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; +import com.polarion.alm.shared.api.utils.collections.StrictMapImpl; +import com.polarion.alm.shared.api.utils.html.RichTextRenderTarget; +import com.polarion.alm.shared.rpe.RpeModelAspect; +import com.polarion.alm.shared.rpe.RpeRenderer; +import com.polarion.alm.tracker.model.ITestRun; +import org.jetbrains.annotations.NotNull; + +public class TestRunAdapter extends CommonUniqueObjectAdapter { + private final @NotNull ITestRun testRun; + + public TestRunAdapter(@NotNull ITestRun testRun) { + this.testRun = testRun; + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull T getUniqueObject() { + return (T) testRun; + } + + @Override + public @NotNull DocumentId getDocumentId() { + return new TestRuntId(getDocumentProject(), testRun.getId()); + } + + private @NotNull DocumentProject getDocumentProject() { + return new DocumentProject(testRun.getProject()); + } + + @Override + public @NotNull DocumentType getDocumentType() { + return DocumentType.TEST_RUN; + } + + @Override + public @NotNull String getTitle() { + return testRun.getLabel(); + } + + @Override + public @NotNull String getContent(@NotNull ExportParams exportParams, @NotNull ReadOnlyTransaction transaction) { + return PolarionBaselineExecutor.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { + ProxyTestRun proxyTestRun = new ProxyTestRun(testRun, (InternalReadOnlyTransaction) transaction); + + String html = RpeModelAspect.getPageHtml(proxyTestRun); + RpeRenderer richPageRenderer = new RpeRenderer((InternalReadOnlyTransaction) transaction, html, RichTextRenderTarget.PDF_EXPORT, proxyTestRun.getReference(), proxyTestRun.getReference().scope(), new StrictMapImpl<>()); + return richPageRenderer.render(null); + }); + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/WikiPageAdapter.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/WikiPageAdapter.java new file mode 100644 index 00000000..bf8597be --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/WikiPageAdapter.java @@ -0,0 +1,60 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentId; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentProject; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveReportId; +import ch.sbb.polarion.extension.pdf_exporter.service.PolarionBaselineExecutor; +import ch.sbb.polarion.extension.pdf_exporter.util.exporter.WikiRenderer; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import com.polarion.alm.tracker.model.IWikiPage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public class WikiPageAdapter extends CommonUniqueObjectAdapter { + private final @NotNull IWikiPage wikiPage; + + public WikiPageAdapter(@NotNull IWikiPage wikiPage) { + this.wikiPage = wikiPage; + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull T getUniqueObject() { + return (T) wikiPage; + } + + @Override + public @NotNull DocumentId getDocumentId() { + return new LiveReportId(getDocumentProject(), wikiPage.getId()); + } + + private @Nullable DocumentProject getDocumentProject() { + return wikiPage.getProject() == null ? null : new DocumentProject(wikiPage.getProject()); + } + + @Override + public @NotNull DocumentType getDocumentType() { + return DocumentType.WIKI_PAGE; + } + + @Override + public @NotNull String getTitle() { + return wikiPage.getTitleOrName(); + } + + @Override + public @NotNull String getContent(@NotNull ExportParams exportParams, @NotNull ReadOnlyTransaction transaction) { + return PolarionBaselineExecutor.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { + @NotNull String projectId = wikiPage.getProject() != null ? wikiPage.getProject().getId() : ""; + @NotNull String locationPath = Objects.requireNonNull(exportParams.getLocationPath()); + @Nullable String revision = exportParams.getRevision(); + return new WikiRenderer().render(projectId, locationPath, revision); + }); + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/DocumentId.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/DocumentId.java new file mode 100644 index 00000000..b2d2a574 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/DocumentId.java @@ -0,0 +1,10 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface DocumentId { + @Nullable DocumentProject getDocumentProject(); + + @NotNull String getDocumentId(); +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/DocumentProject.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/DocumentProject.java new file mode 100644 index 00000000..2a3a4d38 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/DocumentProject.java @@ -0,0 +1,20 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id; + +import com.polarion.alm.projects.model.IProject; +import lombok.Data; +import org.jetbrains.annotations.NotNull; + +@Data +public class DocumentProject { + private final String id; + private final String name; + + public DocumentProject(String id, String name) { + this.id = id; + this.name = name; + } + + public DocumentProject(@NotNull IProject project) { + this(project.getId(), project.getName()); + } +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/LiveDocId.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/LiveDocId.java new file mode 100644 index 00000000..91e334e5 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/LiveDocId.java @@ -0,0 +1,33 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id; + +import org.jetbrains.annotations.NotNull; + +public class LiveDocId implements DocumentId { + private final @NotNull DocumentProject documentProject; + private final @NotNull String spaceId; + private final @NotNull String documentName; + + public LiveDocId(@NotNull DocumentProject documentProject, @NotNull String spaceId, @NotNull String documentName) { + this.documentProject = documentProject; + this.spaceId = spaceId; + this.documentName = documentName; + } + + @Override + public @NotNull DocumentProject getDocumentProject() { + return documentProject; + } + + public @NotNull String getSpaceId() { + return spaceId; + } + + @Override + public @NotNull String getDocumentId() { + return documentName; + } + + public static LiveDocId from(@NotNull String projectId, @NotNull String spaceId, @NotNull String documentName) { + return new LiveDocId(new DocumentProject(projectId, projectId), spaceId, documentName); + } +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/LiveReportId.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/LiveReportId.java new file mode 100644 index 00000000..376cfe3e --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/LiveReportId.java @@ -0,0 +1,24 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class LiveReportId implements DocumentId { + private final @Nullable DocumentProject documentProject; + private final @NotNull String pageId; + + public LiveReportId(@Nullable DocumentProject documentProject, @NotNull String pageId) { + this.documentProject = documentProject; + this.pageId = pageId; + } + + @Override + public @Nullable DocumentProject getDocumentProject() { + return documentProject; + } + + @Override + public @NotNull String getDocumentId() { + return pageId; + } +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/TestRuntId.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/TestRuntId.java new file mode 100644 index 00000000..8d9e6471 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/TestRuntId.java @@ -0,0 +1,23 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id; + +import org.jetbrains.annotations.NotNull; + +public class TestRuntId implements DocumentId { + private final @NotNull DocumentProject documentProject; + private final @NotNull String testRunId; + + public TestRuntId(@NotNull DocumentProject documentProject, @NotNull String testRunId) { + this.documentProject = documentProject; + this.testRunId = testRunId; + } + + @Override + public @NotNull DocumentProject getDocumentProject() { + return documentProject; + } + + @Override + public @NotNull String getDocumentId() { + return testRunId; + } +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/WikiPageId.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/WikiPageId.java new file mode 100644 index 00000000..82ff1073 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/id/WikiPageId.java @@ -0,0 +1,24 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class WikiPageId implements DocumentId { + private final @Nullable DocumentProject documentProject; + private final @NotNull String pageId; + + public WikiPageId(@Nullable DocumentProject documentProject, @NotNull String pageId) { + this.documentProject = documentProject; + this.pageId = pageId; + } + + @Override + public @Nullable DocumentProject getDocumentProject() { + return documentProject; + } + + @Override + public @NotNull String getDocumentId() { + return pageId; + } +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/service/PdfExporterPolarionService.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/service/PdfExporterPolarionService.java index 894de61f..9ce868be 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/service/PdfExporterPolarionService.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/service/PdfExporterPolarionService.java @@ -5,7 +5,6 @@ import ch.sbb.polarion.extension.generic.settings.SettingId; import ch.sbb.polarion.extension.generic.settings.SettingName; import ch.sbb.polarion.extension.generic.util.ScopeUtils; -import ch.sbb.polarion.extension.pdf_exporter.exception.BaselineExecutionException; import ch.sbb.polarion.extension.pdf_exporter.rest.model.attachments.TestRunAttachment; import ch.sbb.polarion.extension.pdf_exporter.rest.model.collections.DocumentCollectionEntry; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.stylepackage.StylePackageModel; @@ -40,7 +39,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.concurrent.Callable; public class PdfExporterPolarionService extends PolarionService { @@ -206,20 +204,4 @@ private boolean sameDocument(@Nullable String projectId, @NotNull String spaceId return result; } - public T executeInBaseline(@Nullable String baselineRevision, @NotNull ReadOnlyTransaction transaction, @NotNull Callable callable) { - if (baselineRevision == null) { - return callCallable(callable); - } else { - return transaction.utils().executeInBaseline(baselineRevision, () -> callCallable(callable)); - } - } - - private static T callCallable(@NotNull Callable callable) { - try { - return callable.call(); - } catch (Exception e) { - throw new BaselineExecutionException("Error during callable execution", e); - } - } - } diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/service/PolarionBaselineExecutor.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/service/PolarionBaselineExecutor.java new file mode 100644 index 00000000..5fa15677 --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/service/PolarionBaselineExecutor.java @@ -0,0 +1,32 @@ +package ch.sbb.polarion.extension.pdf_exporter.service; + +import ch.sbb.polarion.extension.pdf_exporter.exception.BaselineExecutionException; +import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.concurrent.Callable; + +@UtilityClass +public class PolarionBaselineExecutor { + + public T executeInBaseline(@Nullable String baselineRevision, @NotNull ReadOnlyTransaction transaction, @NotNull Callable callable) { + if (baselineRevision == null) { + return callCallable(callable); + } else { + return transaction.utils().executeInBaseline(baselineRevision, () -> callCallable(callable)); + } + } + + private T callCallable(@NotNull Callable callable) { + try { + return callable.call(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new BaselineExecutionException("Error during callable execution", e); + } + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataFactory.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataFactory.java new file mode 100644 index 00000000..168d91ba --- /dev/null +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataFactory.java @@ -0,0 +1,33 @@ +package ch.sbb.polarion.extension.pdf_exporter.util; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.ModelObjectProvider; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.UniqueObjectConverter; +import ch.sbb.polarion.extension.pdf_exporter.service.PolarionBaselineExecutor; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.shared.api.model.ModelObject; +import com.polarion.alm.shared.api.transaction.TransactionalExecutor; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +@UtilityClass +public class DocumentDataFactory { + + public @NotNull DocumentData getDocumentData(@NotNull ExportParams exportParams, boolean withContent) { + return Objects.requireNonNull(TransactionalExecutor.executeSafelyInReadOnlyTransaction( + transaction -> PolarionBaselineExecutor.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { + + ModelObject modelObject = new ModelObjectProvider(exportParams) + .getModelObject(transaction); + + return new UniqueObjectConverter(modelObject) + .withExportParams(exportParams) + .withContent(withContent) + .toDocumentData(transaction); + }))); + } + +} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataHelper.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataHelper.java deleted file mode 100644 index 9d04e5d2..00000000 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataHelper.java +++ /dev/null @@ -1,282 +0,0 @@ -package ch.sbb.polarion.extension.pdf_exporter.util; - -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; -import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; -import ch.sbb.polarion.extension.pdf_exporter.util.exporter.ModifiedDocumentRenderer; -import ch.sbb.polarion.extension.pdf_exporter.util.exporter.WikiRenderer; -import com.polarion.alm.projects.model.IProject; -import com.polarion.alm.projects.model.IUniqueObject; -import com.polarion.alm.server.api.model.document.ProxyDocument; -import com.polarion.alm.shared.api.model.document.Document; -import com.polarion.alm.shared.api.model.document.DocumentReference; -import com.polarion.alm.shared.api.model.rp.RichPage; -import com.polarion.alm.shared.api.model.rp.RichPageReference; -import com.polarion.alm.shared.api.model.tr.TestRun; -import com.polarion.alm.shared.api.model.tr.TestRunReference; -import com.polarion.alm.shared.api.model.wiki.WikiPage; -import com.polarion.alm.shared.api.model.wiki.WikiPageReference; -import com.polarion.alm.shared.api.transaction.TransactionalExecutor; -import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; -import com.polarion.alm.shared.api.utils.collections.StrictMap; -import com.polarion.alm.shared.api.utils.collections.StrictMapImpl; -import com.polarion.alm.shared.api.utils.html.RichTextRenderTarget; -import com.polarion.alm.shared.dle.document.DocumentRendererParameters; -import com.polarion.alm.shared.rpe.RpeModelAspect; -import com.polarion.alm.shared.rpe.RpeRenderer; -import com.polarion.alm.tracker.model.IBaseline; -import com.polarion.alm.tracker.model.IModule; -import com.polarion.alm.tracker.model.IRichPage; -import com.polarion.alm.tracker.model.ITestRun; -import com.polarion.alm.tracker.model.ITrackerProject; -import com.polarion.alm.tracker.model.IWikiPage; -import com.polarion.alm.tracker.model.ipi.IInternalBaselinesManager; -import com.polarion.platform.persistence.model.IPObject; -import com.polarion.subterra.base.location.ILocation; -import com.polarion.subterra.base.location.Location; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.VisibleForTesting; - -import java.util.Map; -import java.util.Objects; - -@SuppressWarnings("java:S1200") -public class DocumentDataHelper { - private static final String DOC_REVISION_CUSTOM_FIELD = "docRevision"; - private static final String URL_QUERY_PARAM_LANGUAGE = "language"; - private static final String URL_QUERY_PARAM_ID = "id"; - - private final PdfExporterPolarionService pdfExporterPolarionService; - - public DocumentDataHelper(PdfExporterPolarionService pdfExporterPolarionService) { - this.pdfExporterPolarionService = pdfExporterPolarionService; - } - - public DocumentData getLiveReport(@Nullable ITrackerProject project, @NotNull ExportParams exportParams) { - return getLiveReport(project, exportParams, true); - } - - public DocumentData getLiveReport(@Nullable ITrackerProject project, @NotNull ExportParams exportParams, boolean withContent) { - return TransactionalExecutor.executeSafelyInReadOnlyTransaction( - transaction -> pdfExporterPolarionService.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { - - String projectId = project != null ? project.getId() : ""; - String locationPath = exportParams.getLocationPath(); - if (locationPath == null) { - throw new IllegalArgumentException("Location path is required for export"); - } - - RichPageReference richPageReference = RichPageReference.fromPath(createPath(projectId, locationPath)); - if (exportParams.getRevision() != null) { - richPageReference = richPageReference.getWithRevision(exportParams.getRevision()); - } - - RichPage richPage = richPageReference.getOriginal(transaction); - - String documentContent = null; - if (withContent) { - String html = RpeModelAspect.getPageHtml(richPage); - Map liveReportParameters = exportParams.getUrlQueryParameters() == null ? Map.of() : exportParams.getUrlQueryParameters(); - StrictMap urlParameters = new StrictMapImpl<>(liveReportParameters); - RpeRenderer richPageRenderer = new RpeRenderer((InternalReadOnlyTransaction) transaction, html, RichTextRenderTarget.PDF_EXPORT, richPageReference, richPageReference.scope(), urlParameters); - documentContent = richPageRenderer.render(null); - } - - return DocumentData.builder(DocumentType.LIVE_REPORT, richPage.getOldApi()) - .projectName(project != null ? project.getName() : "") - .lastRevision(richPage.getOldApi().getLastRevision()) - .baselineName(project != null ? getRevisionBaseline(projectId, richPage.getOldApi(), exportParams.getRevision()) : "") - .id(richPage.getOldApi().getId()) - .title(richPage.getOldApi().getTitleOrName()) - .content(documentContent) - .build(); - })); - } - - public DocumentData getTestRun(@NotNull ITrackerProject project, @NotNull ExportParams exportParams) { - return getTestRun(project, exportParams, true); - } - - public DocumentData getTestRun(@NotNull ITrackerProject project, @NotNull ExportParams exportParams, boolean withContent) { - return TransactionalExecutor.executeSafelyInReadOnlyTransaction( - transaction -> pdfExporterPolarionService.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { - - String projectId = project.getId(); - Map urlQueryParameters = exportParams.getUrlQueryParameters(); - if (urlQueryParameters == null || !urlQueryParameters.containsKey(URL_QUERY_PARAM_ID)) { - throw new IllegalArgumentException("TestRun id is required for export"); - } - - TestRunReference testRunReference = TestRunReference.fromPath(createPath(projectId, urlQueryParameters.get(URL_QUERY_PARAM_ID))); - if (exportParams.getRevision() != null) { - testRunReference = testRunReference.getWithRevision(exportParams.getRevision()); - } - - TestRun testRun = testRunReference.getOriginal(transaction); - - String documentContent = null; - if (withContent) { - String html = RpeModelAspect.getPageHtml(testRun); - RpeRenderer richPageRenderer = new RpeRenderer((InternalReadOnlyTransaction) transaction, html, RichTextRenderTarget.PDF_EXPORT, testRunReference, testRunReference.scope(), new StrictMapImpl<>()); - documentContent = richPageRenderer.render(null); - } - - return DocumentData.builder(DocumentType.TEST_RUN, testRun.getOldApi()) - .projectName(project.getName()) - .lastRevision(testRun.getOldApi().getLastRevision()) - .baselineName(getRevisionBaseline(projectId, testRun.getOldApi(), exportParams.getRevision())) - .id(testRun.getOldApi().getId()) - .title(testRun.getOldApi().getLabel()) - .content(documentContent) - .build(); - })); - } - - public DocumentData getWikiPage(@Nullable ITrackerProject project, @NotNull ExportParams exportParams) { - return getWikiPage(project, exportParams, true); - } - - public DocumentData getWikiPage(@Nullable ITrackerProject project, @NotNull ExportParams exportParams, boolean withContent) { - return TransactionalExecutor.executeSafelyInReadOnlyTransaction( - transaction -> pdfExporterPolarionService.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { - - String projectId = project != null ? project.getId() : ""; - String locationPath = exportParams.getLocationPath(); - if (locationPath == null) { - throw new IllegalArgumentException("Location path is required for export"); - } - - WikiPageReference wikiPageReference = WikiPageReference.fromPath(createPath(projectId, exportParams.getLocationPath())); - if (exportParams.getRevision() != null) { - wikiPageReference = wikiPageReference.getWithRevision(exportParams.getRevision()); - } - - WikiPage wikiPage = wikiPageReference.getOriginal(transaction); - - String documentContent = null; - if (withContent) { - documentContent = new WikiRenderer().render(projectId, exportParams.getLocationPath(), exportParams.getRevision()); - } - - return DocumentData.builder(DocumentType.WIKI_PAGE, wikiPage.getOldApi()) - .projectName(project != null ? project.getName() : "") - .lastRevision(wikiPage.getOldApi().getLastRevision()) - .baselineName(project != null ? getRevisionBaseline(projectId, wikiPage.getOldApi(), exportParams.getRevision()) : "") - .id(wikiPage.getOldApi().getId()) - .title(wikiPage.getOldApi().getTitleOrName()) - .content(documentContent) - .build(); - })); - } - - public DocumentData getLiveDoc(@NotNull ITrackerProject project, @NotNull ExportParams exportParams) { - return getLiveDoc(project, exportParams, true); - } - - public DocumentData getLiveDoc(@NotNull ITrackerProject project, @NotNull ExportParams exportParams, boolean withContent) { - return TransactionalExecutor.executeSafelyInReadOnlyTransaction( - transaction -> pdfExporterPolarionService.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { - - String locationPath = exportParams.getLocationPath(); - if (locationPath == null) { - throw new IllegalArgumentException("Location path is required for export"); - } - - DocumentReference documentReference = DocumentReference.fromPath(createPath(project.getId(), exportParams.getLocationPath())); - if (exportParams.getRevision() != null) { - documentReference = documentReference.getWithRevision(exportParams.getRevision()); - } - - Document document = documentReference.getOriginal(transaction); - - String documentContent = null; - if (withContent) { - ProxyDocument proxyDocument = new ProxyDocument(document.getOldApi(), (InternalReadOnlyTransaction) transaction); - documentContent = getLiveDocContent(exportParams, proxyDocument, (InternalReadOnlyTransaction) transaction); - } - - return DocumentData.builder(DocumentType.LIVE_DOC, document.getOldApi()) - .projectName(project.getName()) - .lastRevision(document.getOldApi().getLastRevision()) - .baselineName(getRevisionBaseline(project.getId(), document.getOldApi(), exportParams.getRevision())) - .id(document.getOldApi().getModuleName()) - .title(document.getOldApi().getTitleOrName()) - .content(documentContent) - .build(); - })); - } - - public String getLiveDocContent(@NotNull ExportParams exportParams, @NotNull ProxyDocument document, @NotNull InternalReadOnlyTransaction transaction) { - String internalContent = exportParams.getInternalContent() != null ? exportParams.getInternalContent() : document.getHomePageContentHtml(); - if (internalContent != null && exportParams.isEnableCommentsRendering()) { - // Add inline comments into document content - internalContent = new LiveDocCommentsProcessor().addLiveDocComments(document, internalContent); - } - Map documentParameters = exportParams.getUrlQueryParameters() == null ? Map.of() : exportParams.getUrlQueryParameters(); - DocumentRendererParameters parameters = new DocumentRendererParameters(null, documentParameters.get(URL_QUERY_PARAM_LANGUAGE)); - ModifiedDocumentRenderer documentRenderer = new ModifiedDocumentRenderer(transaction, document, RichTextRenderTarget.PDF_EXPORT, parameters); - return documentRenderer.render(internalContent != null ? internalContent : ""); - } - - public String getDocumentStatus(String revision, @NotNull DocumentData documentData) { - String documentStatus = documentData.getLastRevision(); - if (revision != null) { - documentStatus = revision; - } else if (documentData.getDocumentObject() instanceof IModule module) { - Object docRevision = module.getCustomField(DOC_REVISION_CUSTOM_FIELD); - if (docRevision != null) { - documentStatus = docRevision.toString(); - } - } - return documentStatus; - } - - public boolean hasLiveDocNestedNumberedLists(@NotNull ExportParams exportParams) { - return Boolean.TRUE.equals(TransactionalExecutor.executeSafelyInReadOnlyTransaction(transaction -> pdfExporterPolarionService.executeInBaseline(exportParams.getBaselineRevision(), transaction, () -> { - IProject project = pdfExporterPolarionService.getProject(Objects.requireNonNull(exportParams.getProjectId())); - ILocation location = getDocumentLocation(exportParams.getLocationPath(), exportParams.getRevision()); - ProxyDocument document = new ProxyDocument(pdfExporterPolarionService.getModule(project, location), (InternalReadOnlyTransaction) transaction); - - String internalContent = document.getHomePageContentHtml(); - DocumentRendererParameters parameters = new DocumentRendererParameters(null, null); - ModifiedDocumentRenderer documentRenderer = new ModifiedDocumentRenderer((InternalReadOnlyTransaction) transaction, document, RichTextRenderTarget.PDF_EXPORT, parameters); - String renderedContent = documentRenderer.render(internalContent != null ? internalContent : ""); - - return new NumberedListsSanitizer().containsNestedNumberedLists(renderedContent); - }))); - } - - public ILocation getDocumentLocation(String locationPath, @Nullable String revision) { - return revision == null ? Location.getLocation(locationPath) : Location.getLocationWithRevision(locationPath, revision); - } - - @VisibleForTesting - static @NotNull String createPath(@NotNull String projectId, @NotNull String locationPath) { - return String.format("%s/%s", projectId, locationPath); - } - - @NotNull - private String getRevisionBaseline(@NotNull String projectId, @NotNull IPObject iPObject, @Nullable String revision) { - IInternalBaselinesManager baselinesManager = (IInternalBaselinesManager) pdfExporterPolarionService.getTrackerProject(projectId).getBaselinesManager(); - revision = revision == null ? iPObject.getLastRevision() : revision; - - StringBuilder baselineNameBuilder = new StringBuilder(); - - IBaseline projectBaseline = baselinesManager.getRevisionBaseline(revision); - if (projectBaseline != null) { - baselineNameBuilder.append("pb. ").append(projectBaseline.getName()); - } - - IBaseline moduleBaseline = baselinesManager.getRevisionBaseline(iPObject, revision); - if (moduleBaseline != null) { - if (!baselineNameBuilder.isEmpty()) { - baselineNameBuilder.append(" | "); - } - baselineNameBuilder.append("db. ").append(moduleBaseline.getName()); - } - - return baselineNameBuilder.toString(); - } -} diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentFileNameHelper.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentFileNameHelper.java index c3d894f2..7865b188 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentFileNameHelper.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentFileNameHelper.java @@ -4,55 +4,38 @@ import ch.sbb.polarion.extension.generic.settings.NamedSettingsRegistry; import ch.sbb.polarion.extension.generic.settings.SettingId; import ch.sbb.polarion.extension.generic.util.ScopeUtils; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.filename.FileNameTemplateModel; -import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; import ch.sbb.polarion.extension.pdf_exporter.settings.FileNameTemplateSettings; import ch.sbb.polarion.extension.pdf_exporter.util.placeholder.PlaceholderProcessor; import ch.sbb.polarion.extension.pdf_exporter.util.velocity.VelocityEvaluator; import com.polarion.alm.projects.model.IUniqueObject; -import com.polarion.alm.tracker.model.ITrackerProject; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.VisibleForTesting; import java.util.EnumSet; -import java.util.Objects; public class DocumentFileNameHelper { - private final PdfExporterPolarionService pdfExporterPolarionService; private final VelocityEvaluator velocityEvaluator; - public DocumentFileNameHelper(PdfExporterPolarionService pdfExporterPolarionService) { - this.pdfExporterPolarionService = pdfExporterPolarionService; + public DocumentFileNameHelper() { this.velocityEvaluator = new VelocityEvaluator(); } - public DocumentFileNameHelper(PdfExporterPolarionService pdfExporterPolarionService, VelocityEvaluator velocityEvaluator) { - this.pdfExporterPolarionService = pdfExporterPolarionService; + public DocumentFileNameHelper(VelocityEvaluator velocityEvaluator) { this.velocityEvaluator = velocityEvaluator; } public String getDocumentFileName(@NotNull ExportParams exportParams) { - ITrackerProject project = null; - if (exportParams.getProjectId() != null) { - project = pdfExporterPolarionService.getTrackerProject(exportParams.getProjectId()); - } else if (EnumSet.of(DocumentType.LIVE_DOC, DocumentType.TEST_RUN).contains(exportParams.getDocumentType())) { + if (exportParams.getProjectId() == null && EnumSet.of(DocumentType.LIVE_DOC, DocumentType.TEST_RUN).contains(exportParams.getDocumentType())) { throw new IllegalArgumentException("Project ID must be provided for LiveDoc or TestRun export"); } - DocumentDataHelper documentDataHelper = new DocumentDataHelper(pdfExporterPolarionService); - final DocumentData documentData = - switch (exportParams.getDocumentType()) { - case LIVE_DOC -> documentDataHelper.getLiveDoc(Objects.requireNonNull(project), exportParams, false); - case LIVE_REPORT -> documentDataHelper.getLiveReport(project, exportParams, false); - case TEST_RUN -> documentDataHelper.getTestRun(Objects.requireNonNull(project), exportParams, false); - case WIKI_PAGE -> documentDataHelper.getWikiPage(project, exportParams, false); - case BASELINE_COLLECTION -> throw new IllegalArgumentException("Unsupported document type: %s".formatted(exportParams.getDocumentType())); - }; + final DocumentData documentData = DocumentDataFactory.getDocumentData(exportParams, false); FileNameTemplateModel fileNameTemplateModel = getFileNameTemplateModel(ScopeUtils.getScopeFromProject(exportParams.getProjectId())); @NotNull String fileNameTemplate = getFileNameTemplate(exportParams.getDocumentType(), fileNameTemplateModel); diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/placeholder/PlaceholderProcessor.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/placeholder/PlaceholderProcessor.java index 14d66dc6..02f86bea 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/placeholder/PlaceholderProcessor.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/placeholder/PlaceholderProcessor.java @@ -1,11 +1,10 @@ package ch.sbb.polarion.extension.pdf_exporter.util.placeholder; import ch.sbb.polarion.extension.generic.regex.RegexMatcher; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.headerfooter.Placeholder; import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; -import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataHelper; import com.polarion.alm.projects.model.IUniqueObject; import com.polarion.alm.tracker.model.IModule; import org.jetbrains.annotations.NotNull; @@ -19,21 +18,13 @@ public class PlaceholderProcessor { private final PdfExporterPolarionService pdfExporterPolarionService; - private final DocumentDataHelper documentDataHelper; public PlaceholderProcessor() { this.pdfExporterPolarionService = new PdfExporterPolarionService(); - this.documentDataHelper = new DocumentDataHelper(pdfExporterPolarionService); } public PlaceholderProcessor(PdfExporterPolarionService pdfExporterPolarionService) { this.pdfExporterPolarionService = pdfExporterPolarionService; - this.documentDataHelper = new DocumentDataHelper(pdfExporterPolarionService); - } - - public PlaceholderProcessor(PdfExporterPolarionService pdfExporterPolarionService, DocumentDataHelper documentDataHelper) { - this.pdfExporterPolarionService = pdfExporterPolarionService; - this.documentDataHelper = documentDataHelper; } public @NotNull String replacePlaceholders(@NotNull DocumentData documentData, @NotNull ExportParams exportParams, @NotNull String template) { @@ -49,22 +40,24 @@ public PlaceholderProcessor(PdfExporterPolarionService pdfExporterPolarionServic public @NotNull PlaceholderValues getPlaceholderValues(@NotNull DocumentData documentData, @NotNull ExportParams exportParams, @NotNull List templates) { String revision = exportParams.getRevision() != null ? exportParams.getRevision() : documentData.getLastRevision(); - String baseLineName = documentData.getBaselineName(); + String baselineName = documentData.getBaseline() != null ? documentData.getBaseline().asPlaceholder() : ""; PlaceholderValues placeholderValues = PlaceholderValues.builder() .productName(pdfExporterPolarionService.getPolarionProductName()) .productVersion(pdfExporterPolarionService.getPolarionVersion()) - .projectName(documentData.getProjectName()) + .projectName(documentData.getId().getDocumentProject() != null ? documentData.getId().getDocumentProject().getName() : "") .revision(revision) - .revisionAndBaseLineName(baseLineName != null ? (revision + " " + baseLineName) : revision) - .baseLineName(baseLineName) - .documentId(documentData.getId()) + .revisionAndBaseLineName(baselineName.isEmpty() ? revision : (revision + " " + baselineName)) + .baseLineName(baselineName) + .documentId(documentData.getId().getDocumentId()) .documentTitle(documentData.getTitle()) - .documentRevision(documentDataHelper.getDocumentStatus(exportParams.getRevision(), documentData)) + .documentRevision(documentData.getRevisionPlaceholder()) .build(); + if (documentData.getDocumentObject() instanceof IModule module) { placeholderValues.addCustomVariables(module, extractCustomPlaceholders(templates)); } + return placeholderValues; } diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/velocity/VelocityEvaluator.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/velocity/VelocityEvaluator.java index 8551f179..4f5bbc3b 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/velocity/VelocityEvaluator.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/util/velocity/VelocityEvaluator.java @@ -1,7 +1,7 @@ package ch.sbb.polarion.extension.pdf_exporter.util.velocity; import ch.sbb.polarion.extension.generic.util.ObjectUtils; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; import com.polarion.alm.projects.model.IUniqueObject; import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; import com.polarion.alm.shared.api.transaction.TransactionalExecutor; @@ -45,7 +45,7 @@ public class VelocityEvaluator { private @NotNull VelocityContext createVelocityContext(@NotNull ReadOnlyTransaction transaction, @NotNull DocumentData documentData) { VelocityContext velocityContext = new VelocityContextInitializer(transaction).create(); - switch (documentData.getDocumentType()) { + switch (documentData.getType()) { case LIVE_DOC -> { if (documentData.getDocumentObject() instanceof IModule) { velocityContext.put("document", documentData.getDocumentObject()); @@ -73,7 +73,7 @@ public class VelocityEvaluator { } } - velocityContext.put("projectName", documentData.getProjectName()); + velocityContext.put("projectName", documentData.getId().getDocumentProject() != null ? documentData.getId().getDocumentProject().getName() : ""); return velocityContext; } diff --git a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/widgets/ExportToPdfButton.java b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/widgets/ExportToPdfButton.java index c1c87dcf..e92de7ce 100644 --- a/src/main/java/ch/sbb/polarion/extension/pdf_exporter/widgets/ExportToPdfButton.java +++ b/src/main/java/ch/sbb/polarion/extension/pdf_exporter/widgets/ExportToPdfButton.java @@ -4,7 +4,6 @@ import com.polarion.alm.shared.api.SharedContext; import com.polarion.alm.shared.api.model.rp.parameter.ParameterFactory; import com.polarion.alm.shared.api.model.rp.parameter.RichPageParameter; -import com.polarion.alm.shared.api.model.rp.widget.RichPageWidget; import com.polarion.alm.shared.api.model.rp.widget.RichPageWidgetContext; import com.polarion.alm.shared.api.model.rp.widget.RichPageWidgetRenderingContext; import com.polarion.alm.shared.api.utils.collections.ImmutableStrictList; diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/converter/CoverPageProcessorTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/converter/CoverPageProcessorTest.java index 48c6ba77..f2a8414c 100644 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/converter/CoverPageProcessorTest.java +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/converter/CoverPageProcessorTest.java @@ -3,9 +3,11 @@ import ch.sbb.polarion.extension.generic.settings.SettingId; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentProject; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveDocId; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.coverpage.CoverPageModel; import ch.sbb.polarion.extension.pdf_exporter.settings.CoverPageSettings; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.util.PdfGenerationLog; import ch.sbb.polarion.extension.pdf_exporter.util.PdfTemplateProcessor; import ch.sbb.polarion.extension.pdf_exporter.util.placeholder.PlaceholderProcessor; @@ -110,9 +112,11 @@ void shouldComposeTitleHtml() { private DocumentData prepareMocks(CoverPageModel coverPageModel, ExportParams exportParams) { when(coverPageSettings.load("testProjectId", SettingId.fromName("test cover page"))).thenReturn(coverPageModel); - DocumentData documentData = DocumentData.builder(DocumentType.LIVE_DOC, mock(IModule.class)) - .id("test id") + DocumentData documentData = DocumentData.creator(DocumentType.LIVE_DOC, mock(IModule.class)) + .id(new LiveDocId(new DocumentProject("testProjectId", "Test Project"), "_default", "test id")) .title("test document") + .lastRevision("12345") + .revisionPlaceholder("12345") .build(); when(placeholderProcessor.replacePlaceholders(documentData, exportParams, "test template html")).thenReturn("replaced template html"); when(velocityEvaluator.evaluateVelocityExpressions(eq(documentData), anyString())).thenAnswer(a -> a.getArguments()[1]); @@ -120,4 +124,4 @@ private DocumentData prepareMocks(CoverPageModel coverPageModel, Export when(pdfTemplateProcessor.processUsing(exportParams, "test document", "test template css", "replaced template html")).thenReturn("result title html"); return documentData; } -} \ No newline at end of file +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/converter/PdfConverterTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/converter/PdfConverterTest.java index f6cd11ee..71d234b7 100644 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/converter/PdfConverterTest.java +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/converter/PdfConverterTest.java @@ -3,16 +3,17 @@ import ch.sbb.polarion.extension.generic.settings.SettingId; import ch.sbb.polarion.extension.pdf_exporter.TestStringUtils; import ch.sbb.polarion.extension.pdf_exporter.configuration.PdfExporterExtensionConfigurationExtension; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.ExportMetaInfoCallback; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveDocId; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.css.CssModel; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.headerfooter.HeaderFooterModel; import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; import ch.sbb.polarion.extension.pdf_exporter.settings.CssSettings; import ch.sbb.polarion.extension.pdf_exporter.settings.HeaderFooterSettings; -import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataHelper; +import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataFactory; import ch.sbb.polarion.extension.pdf_exporter.util.HtmlProcessor; import ch.sbb.polarion.extension.pdf_exporter.util.PdfGenerationLog; import ch.sbb.polarion.extension.pdf_exporter.util.PdfTemplateProcessor; @@ -28,6 +29,8 @@ import com.polarion.alm.tracker.model.ITypeOpt; import com.polarion.platform.persistence.IEnumeration; import com.polarion.platform.persistence.spi.EnumOption; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -35,6 +38,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; @@ -51,8 +55,6 @@ class PdfConverterTest { @Mock private IModule module; @Mock - private DocumentDataHelper documentDataHelper; - @Mock private CssSettings cssSettings; @Mock private HeaderFooterSettings headerFooterSettings; @@ -69,25 +71,41 @@ class PdfConverterTest { @Mock private PdfTemplateProcessor pdfTemplateProcessor; + private MockedStatic documentDataFactoryMockedStatic; + + @BeforeEach + void setUp() { + documentDataFactoryMockedStatic = mockStatic(DocumentDataFactory.class); + } + + @AfterEach + void tearDown() { + documentDataFactoryMockedStatic.close(); + } + @Test void shouldConvertToPdfInSimplestWorkflow() { // Arrange ExportParams exportParams = ExportParams.builder() - .projectId("test project") + .projectId("testProjectId") .documentType(DocumentType.LIVE_DOC) .build(); + ITrackerProject project = mock(ITrackerProject.class); - lenient().when(pdfExporterPolarionService.getTrackerProject("test project")).thenReturn(project); - PdfConverter pdfConverter = new PdfConverter(pdfExporterPolarionService, headerFooterSettings, cssSettings, documentDataHelper, placeholderProcessor, velocityEvaluator, coverPageProcessor, weasyPrintServiceConnector, htmlProcessor, pdfTemplateProcessor); + lenient().when(pdfExporterPolarionService.getTrackerProject("testProjectId")).thenReturn(project); + PdfConverter pdfConverter = new PdfConverter(pdfExporterPolarionService, headerFooterSettings, cssSettings, placeholderProcessor, velocityEvaluator, coverPageProcessor, weasyPrintServiceConnector, htmlProcessor, pdfTemplateProcessor); CssModel cssModel = CssModel.builder().css("test css").build(); - when(cssSettings.load("test project", SettingId.fromName("Default"))).thenReturn(cssModel); - DocumentData documentData = DocumentData.builder(DocumentType.LIVE_DOC, module) - .id("testDocumentId") + when(cssSettings.load("testProjectId", SettingId.fromName("Default"))).thenReturn(cssModel); + DocumentData documentData = DocumentData.creator(DocumentType.LIVE_DOC, module) + .id(LiveDocId.from("testProjectId", "_default", "testDocumentId")) .title("testDocument") .content("test document content") + .lastRevision("12345") + .revisionPlaceholder("12345") .build(); - when(documentDataHelper.getLiveDoc(project, exportParams)).thenReturn(documentData); - when(headerFooterSettings.load("test project", SettingId.fromName("Default"))).thenReturn(HeaderFooterModel.builder().build()); + + documentDataFactoryMockedStatic.when(() -> DocumentDataFactory.getDocumentData(eq(exportParams), anyBoolean())).thenReturn(documentData); + when(headerFooterSettings.load("testProjectId", SettingId.fromName("Default"))).thenReturn(HeaderFooterModel.builder().build()); when(placeholderProcessor.replacePlaceholders(documentData, exportParams, "test css")).thenReturn("css content"); when(placeholderProcessor.replacePlaceholders(eq(documentData), eq(exportParams), anyList())).thenReturn(List.of("hl", "hc", "hr", "fl", "fc", "fr")); when(velocityEvaluator.evaluateVelocityExpressions(eq(documentData), anyString())).thenAnswer(a -> a.getArguments()[1]); @@ -105,10 +123,10 @@ void shouldConvertToPdfInSimplestWorkflow() { @Test void shouldGetAndReplaceCss() { - DocumentData documentData = DocumentData.builder(DocumentType.LIVE_DOC, module) - .id("testDocumentId") - .projectName("testProjectName") + DocumentData documentData = DocumentData.creator(DocumentType.LIVE_DOC, module) + .id(LiveDocId.from("testProjectId", "_default", "testDocumentId")) .lastRevision("testLastRevision") + .revisionPlaceholder("testRevisionPlaceholder") .title("testDocumentTitle") .build(); @@ -121,11 +139,10 @@ void shouldGetAndReplaceCss() { CssModel cssModel = CssModel.builder().css("my test css: {{ DOCUMENT_TITLE }} {{DOCUMENT_REVISION}} {{ REVISION }} {{ PRODUCT_NAME }} {{ PRODUCT_VERSION }} {{customField}}").build(); when(cssSettings.load("testProjectId", SettingId.fromName("testCssSetting"))).thenReturn(cssModel); - PlaceholderProcessor processor = new PlaceholderProcessor(pdfExporterPolarionService, documentDataHelper); + PlaceholderProcessor processor = new PlaceholderProcessor(pdfExporterPolarionService); when(velocityEvaluator.evaluateVelocityExpressions(eq(documentData), anyString())).thenAnswer(a -> a.getArguments()[1]); - PdfConverter pdfConverter = new PdfConverter(null, null, cssSettings, null, processor, velocityEvaluator, null, null, htmlProcessor, pdfTemplateProcessor); + PdfConverter pdfConverter = new PdfConverter(null, null, cssSettings, processor, velocityEvaluator, null, null, htmlProcessor, pdfTemplateProcessor); - when(documentDataHelper.getDocumentStatus("testRevision", documentData)).thenReturn("testStatus"); when(pdfExporterPolarionService.getPolarionProductName()).thenReturn("testProductName"); when(pdfExporterPolarionService.getPolarionVersion()).thenReturn("testVersion"); lenient().when(module.getCustomField("customField")).thenReturn("customValue"); @@ -133,7 +150,7 @@ void shouldGetAndReplaceCss() { String cssContent = pdfConverter.getCssContent(documentData, exportParams); - assertThat(cssContent).startsWith("my test css: testDocumentTitle testStatus testRevision testProductName testVersion customValue"); + assertThat(cssContent).startsWith("my test css: testDocumentTitle testRevisionPlaceholder testRevision testProductName testVersion customValue"); } @ParameterizedTest @@ -141,9 +158,11 @@ void shouldGetAndReplaceCss() { @SuppressWarnings("unchecked") void shouldGetAndProcessHeaderFooterContent(String settingName, String settingArgument) { // Arrange - DocumentData documentData = DocumentData.builder(DocumentType.LIVE_DOC, module) - .id("testDocumentId") + DocumentData documentData = DocumentData.creator(DocumentType.LIVE_DOC, module) + .id(LiveDocId.from("testProjectId", "_default", "testDocumentId")) .title("testDocumentTitle") + .lastRevision("12345") + .revisionPlaceholder("12345") .build(); ExportParams exportParams = ExportParams.builder() .headerFooter(settingName) @@ -171,7 +190,7 @@ void shouldGetAndProcessHeaderFooterContent(String settingName, String settingAr when(htmlProcessor.replaceResourcesAsBase64Encoded(anyString())).thenAnswer(a -> a.getArgument(0)); // Act - PdfConverter pdfConverter = new PdfConverter(null, headerFooterSettings, null, null, placeholderProcessor, velocityEvaluator, null, null, htmlProcessor, null); + PdfConverter pdfConverter = new PdfConverter(null, headerFooterSettings, null, placeholderProcessor, velocityEvaluator, null, null, htmlProcessor, null); String headerFooterContent = pdfConverter.getHeaderFooterContent(documentData, exportParams); // Assert @@ -241,7 +260,7 @@ void shouldPostProcessDocumentContent() { when(htmlProcessor.processHtmlForPDF(anyString(), eq(exportParams), any(List.class))).thenReturn("result string"); // Act - PdfConverter pdfConverter = new PdfConverter(null, null, null, null, null, null, null, null, htmlProcessor, null); + PdfConverter pdfConverter = new PdfConverter(null, null, null, null, null, null, null, htmlProcessor, null); String resultContent = pdfConverter.postProcessDocumentContent(exportParams, project, "test content"); // Assert @@ -255,9 +274,11 @@ void shouldPostProcessDocumentContent() { @MethodSource("paramsForGeneratePdf") void shouldGeneratePdf(String internalContent, String coverPage, ExportMetaInfoCallback metaInfoCallback, boolean useCoverPageProcessor) { // Arrange - DocumentData documentData = DocumentData.builder(DocumentType.LIVE_DOC, module) - .id("testDocumentId") + DocumentData documentData = DocumentData.creator(DocumentType.LIVE_DOC, module) + .id(LiveDocId.from("testProjectId", "_default", "testDocumentId")) .title("testDocumentTitle") + .lastRevision("12345") + .revisionPlaceholder("12345") .build(); ExportParams exportParams = ExportParams.builder() .internalContent(internalContent) @@ -271,7 +292,7 @@ void shouldGeneratePdf(String internalContent, String coverPage, ExportMetaInfoC } // Act - PdfConverter pdfConverter = new PdfConverter(null, null, null, null, null, null, coverPageProcessor, weasyPrintServiceConnector, null, null); + PdfConverter pdfConverter = new PdfConverter(null, null, null, null, null, coverPageProcessor, weasyPrintServiceConnector, null, null); byte[] result = pdfConverter.generatePdf(documentData, exportParams, metaInfoCallback, "test html content", pdfGenerationLog); // Assert @@ -292,4 +313,4 @@ private static Stream paramsForGeneratePdf() { Arguments.of(null, null, null, false) ); } -} \ No newline at end of file +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentDataTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentDataTest.java new file mode 100644 index 00000000..0c7b3a03 --- /dev/null +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/DocumentDataTest.java @@ -0,0 +1,379 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents; + +import ch.sbb.polarion.extension.generic.test_extensions.CustomExtensionMock; +import ch.sbb.polarion.extension.generic.test_extensions.TransactionalExecutorExtension; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveDocId; +import ch.sbb.polarion.extension.pdf_exporter.util.exporter.ModifiedDocumentRenderer; +import ch.sbb.polarion.extension.pdf_exporter.util.exporter.WikiRenderer; +import com.polarion.alm.projects.model.IProject; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.server.api.model.document.ProxyDocument; +import com.polarion.alm.server.api.model.rp.ProxyRichPage; +import com.polarion.alm.server.api.model.tr.ProxyTestRun; +import com.polarion.alm.shared.api.Scope; +import com.polarion.alm.shared.api.model.rp.RichPageReference; +import com.polarion.alm.shared.api.model.tr.TestRunReference; +import com.polarion.alm.shared.api.services.internal.InternalServices; +import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; +import com.polarion.alm.shared.rpe.RpeModelAspect; +import com.polarion.alm.shared.rpe.RpeRenderer; +import com.polarion.alm.tracker.ITrackerService; +import com.polarion.alm.tracker.model.IBaseline; +import com.polarion.alm.tracker.model.IModule; +import com.polarion.alm.tracker.model.IRichPage; +import com.polarion.alm.tracker.model.ITestRun; +import com.polarion.alm.tracker.model.ITrackerProject; +import com.polarion.alm.tracker.model.IWikiPage; +import com.polarion.alm.tracker.model.baselinecollection.IBaselineCollection; +import com.polarion.alm.tracker.model.ipi.IInternalBaselinesManager; +import com.polarion.alm.tracker.spi.model.IInternalModule; +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.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith({MockitoExtension.class, TransactionalExecutorExtension.class}) +class DocumentDataTest { + + @CustomExtensionMock + private InternalReadOnlyTransaction internalReadOnlyTransactionMock; + + @Mock + private IInternalBaselinesManager internalBaselinesManager; + @Mock + private IInternalModule module; + @Mock + private IRichPage richPageInDefaultRepo; + @Mock + private IRichPage richPageInProject; + @Mock + private ITestRun testRun; + @Mock + private IWikiPage wikiPageInDefaultRepo; + @Mock + private IWikiPage wikiPageInProject; + @Mock + private IBaselineCollection baselineCollection; + + @BeforeEach + void setUp() { + InternalServices internalServicesMock = mock(InternalServices.class); + ITrackerService trackerServiceMock = mock(ITrackerService.class); + ITrackerProject trackerProjectMock = mock(ITrackerProject.class); + lenient().when(trackerProjectMock.getBaselinesManager()).thenReturn(internalBaselinesManager); + lenient().when(trackerServiceMock.getTrackerProject((IProject) any())).thenReturn(trackerProjectMock); + lenient().when(internalServicesMock.trackerService()).thenReturn(trackerServiceMock); + lenient().when(internalReadOnlyTransactionMock.services()).thenReturn(internalServicesMock); + + mockDocumentBaseline(module); + mockDocumentBaseline(richPageInDefaultRepo); + mockDocumentBaseline(richPageInProject); + mockDocumentBaseline(testRun); + mockDocumentBaseline(wikiPageInDefaultRepo); + mockDocumentBaseline(wikiPageInProject); + } + + private void mockDocumentBaseline(IUniqueObject uniqueObject) { + IBaseline documentBaselineName = mock(IBaseline.class); + lenient().when(documentBaselineName.getName()).thenReturn("documentBaselineName"); + lenient().when(internalBaselinesManager.getRevisionBaseline(uniqueObject, "12345")).thenReturn(documentBaselineName); + IBaseline projectBaselineName = mock(IBaseline.class); + lenient().when(projectBaselineName.getName()).thenReturn("projectBaselineName"); + lenient().when(internalBaselinesManager.getRevisionBaseline("12345")).thenReturn(projectBaselineName); + } + + @Test + void testLiveDocDocumentData() { + when(module.getId()).thenReturn("module id"); + when(module.getLastRevision()).thenReturn("12345"); + ITrackerProject project = mock(ITrackerProject.class); + when(project.getId()).thenReturn("project id"); + when(project.getName()).thenReturn("project name"); + when(module.getProject()).thenReturn(project); + when(module.getModuleFolder()).thenReturn("_default"); + when(module.getTitleOrName()).thenReturn("module title"); + + UniqueObjectConverter uniqueObjectConverter = new UniqueObjectConverter(module); + DocumentData documentData = uniqueObjectConverter.toDocumentData(); + + assertEquals("project id", documentData.getId().getDocumentProject().getId()); + assertEquals("project name", documentData.getId().getDocumentProject().getName()); + assertEquals("_default", ((LiveDocId) documentData.getId()).getSpaceId()); + assertEquals("module id", documentData.getId().getDocumentId()); + assertEquals(DocumentType.LIVE_DOC, documentData.getType()); + assertEquals("module title", documentData.getTitle()); + assertNull(documentData.getContent()); + assertNotNull(documentData.getBaseline()); + assertEquals("pb. projectBaselineName | db. documentBaselineName", documentData.getBaseline().asPlaceholder()); + assertNotNull(uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline()); + assertEquals("pb. projectBaselineName | db. documentBaselineName", uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline().asPlaceholder()); + assertNull(documentData.getRevision()); + assertEquals("12345", documentData.getLastRevision()); + assertNull(documentData.getContent()); + + ExportParams exportParams = ExportParams.builder() + .locationPath("location path") + .build(); + + try ( + MockedConstruction proxyDocumentMockedConstruction = mockConstruction(ProxyDocument.class, (mock, context) -> { + when(mock.getHomePageContentHtml()).thenReturn(""); + }); + MockedConstruction modifiedDocumentRendererMockedConstruction = mockConstruction(ModifiedDocumentRenderer.class, (mock, context) -> { + when(mock.render(anyString())).thenReturn("test content"); + }) + ) { + DocumentData documentDataWithContent = uniqueObjectConverter + .withContent(true) + .withExportParams(exportParams) + .toDocumentData(); + assertEquals("test content", documentDataWithContent.getContent()); + } + } + + @Test + void testLiveReportDocumentData() { + when(richPageInProject.getId()).thenReturn("rich page id"); + when(richPageInProject.getLastRevision()).thenReturn("12345"); + ITrackerProject project = mock(ITrackerProject.class); + when(project.getId()).thenReturn("project id"); + when(project.getName()).thenReturn("project name"); + when(richPageInProject.getProject()).thenReturn(project); + when(richPageInProject.getTitleOrName()).thenReturn("rich page title"); + + UniqueObjectConverter uniqueObjectConverter = new UniqueObjectConverter(richPageInProject); + DocumentData documentData = uniqueObjectConverter.toDocumentData(); + + assertEquals("project id", documentData.getId().getDocumentProject().getId()); + assertEquals("project name", documentData.getId().getDocumentProject().getName()); + assertEquals("rich page id", documentData.getId().getDocumentId()); + assertEquals(DocumentType.LIVE_REPORT, documentData.getType()); + assertEquals("rich page title", documentData.getTitle()); + assertNull(documentData.getContent()); + assertNotNull(documentData.getBaseline()); + assertEquals("pb. projectBaselineName | db. documentBaselineName", documentData.getBaseline().asPlaceholder()); + assertNotNull(uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline()); + assertEquals("pb. projectBaselineName | db. documentBaselineName", uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline().asPlaceholder()); + assertNull(documentData.getRevision()); + assertEquals("12345", documentData.getLastRevision()); + assertNull(documentData.getContent()); + + ExportParams exportParams = ExportParams.builder() + .locationPath("location path") + .build(); + + try ( + MockedStatic rpeModelAspectMockedStatic = mockStatic(RpeModelAspect.class); + MockedConstruction proxyRichPageMockedConstruction = mockConstruction(ProxyRichPage.class, (mock, context) -> { + RichPageReference referenceRichPageMock = mock(RichPageReference.class); + when(mock.getReference()).thenReturn(referenceRichPageMock); + when(referenceRichPageMock.scope()).thenReturn(mock(Scope.class)); + }); + + MockedConstruction modifiedDocumentRendererMockedConstruction = mockConstruction(RpeRenderer.class, (mock, context) -> { + when(mock.render(null)).thenReturn("test content"); + }) + ) { + DocumentData documentDataWithContent = uniqueObjectConverter + .withContent(true) + .withExportParams(exportParams) + .toDocumentData(); + assertEquals("test content", documentDataWithContent.getContent()); + } + } + + @Test + void testLiveReportInDefaultRepoDocumentData() { + when(richPageInDefaultRepo.getId()).thenReturn("rich page id"); + when(richPageInDefaultRepo.getLastRevision()).thenReturn("12345"); + when(richPageInDefaultRepo.getProject()).thenReturn(null); + when(richPageInDefaultRepo.getTitleOrName()).thenReturn("rich page title"); + + UniqueObjectConverter uniqueObjectConverter = new UniqueObjectConverter(richPageInDefaultRepo); + DocumentData documentData = uniqueObjectConverter.toDocumentData(); + + assertNull(documentData.getId().getDocumentProject()); + assertEquals("rich page id", documentData.getId().getDocumentId()); + assertEquals(DocumentType.LIVE_REPORT, documentData.getType()); + assertEquals("rich page title", documentData.getTitle()); + assertNull(documentData.getContent()); + assertNotNull(documentData.getBaseline()); + assertEquals("", documentData.getBaseline().asPlaceholder()); + assertNotNull(uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline()); + assertEquals("", uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline().asPlaceholder()); + assertNull(documentData.getRevision()); + assertEquals("12345", documentData.getLastRevision()); + assertNull(documentData.getContent()); + + ExportParams exportParams = ExportParams.builder() + .locationPath("location path") + .build(); + + try ( + MockedStatic rpeModelAspectMockedStatic = mockStatic(RpeModelAspect.class); + MockedConstruction proxyRichPageMockedConstruction = mockConstruction(ProxyRichPage.class, (mock, context) -> { + RichPageReference referenceRichPageMock = mock(RichPageReference.class); + when(mock.getReference()).thenReturn(referenceRichPageMock); + when(referenceRichPageMock.scope()).thenReturn(mock(Scope.class)); + }); + + MockedConstruction modifiedDocumentRendererMockedConstruction = mockConstruction(RpeRenderer.class, (mock, context) -> { + when(mock.render(null)).thenReturn("test content"); + }) + ) { + DocumentData documentDataWithContent = uniqueObjectConverter + .withContent(true) + .withExportParams(exportParams) + .toDocumentData(); + assertEquals("test content", documentDataWithContent.getContent()); + } + } + + @Test + void testTestRunDocumentData() { + when(testRun.getId()).thenReturn("test run id"); + when(testRun.getLastRevision()).thenReturn("12345"); + ITrackerProject project = mock(ITrackerProject.class); + when(project.getId()).thenReturn("project id"); + when(project.getName()).thenReturn("project name"); + when(testRun.getProject()).thenReturn(project); + when(testRun.getLabel()).thenReturn("test run title"); + + UniqueObjectConverter uniqueObjectConverter = new UniqueObjectConverter(testRun); + DocumentData documentData = uniqueObjectConverter.toDocumentData(); + + assertEquals("project id", documentData.getId().getDocumentProject().getId()); + assertEquals("project name", documentData.getId().getDocumentProject().getName()); + assertEquals("test run id", documentData.getId().getDocumentId()); + assertEquals(DocumentType.TEST_RUN, documentData.getType()); + assertEquals("test run title", documentData.getTitle()); + assertNull(documentData.getContent()); + assertNotNull(documentData.getBaseline()); + assertEquals("pb. projectBaselineName | db. documentBaselineName", documentData.getBaseline().asPlaceholder()); + assertNotNull(uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline()); + assertEquals("pb. projectBaselineName | db. documentBaselineName", uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline().asPlaceholder()); + assertNull(documentData.getRevision()); + assertEquals("12345", documentData.getLastRevision()); + assertNull(documentData.getContent()); + + ExportParams exportParams = ExportParams.builder() + .locationPath("location path") + .build(); + + try ( + MockedStatic rpeModelAspectMockedStatic = mockStatic(RpeModelAspect.class); + MockedConstruction proxyTestRunMockedConstruction = mockConstruction(ProxyTestRun.class, (mock, context) -> { + TestRunReference referenceRichPageMock = mock(TestRunReference.class); + when(mock.getReference()).thenReturn(referenceRichPageMock); + when(referenceRichPageMock.scope()).thenReturn(mock(Scope.class)); + }); + + MockedConstruction modifiedDocumentRendererMockedConstruction = mockConstruction(RpeRenderer.class, (mock, context) -> { + when(mock.render(null)).thenReturn("test content"); + }) + ) { + DocumentData documentDataWithContent = uniqueObjectConverter + .withContent(true) + .withExportParams(exportParams) + .toDocumentData(); + assertEquals("test content", documentDataWithContent.getContent()); + } + } + + @Test + void testWikiPageInProjectDocumentData() { + when(wikiPageInProject.getId()).thenReturn("wiki page id"); + when(wikiPageInProject.getLastRevision()).thenReturn("12345"); + ITrackerProject project = mock(ITrackerProject.class); + when(project.getId()).thenReturn("project id"); + when(project.getName()).thenReturn("project name"); + when(wikiPageInProject.getProject()).thenReturn(project); + when(wikiPageInProject.getTitleOrName()).thenReturn("wiki page title"); + + UniqueObjectConverter uniqueObjectConverter = new UniqueObjectConverter(wikiPageInProject); + DocumentData documentData = uniqueObjectConverter.toDocumentData(); + + assertEquals("project id", documentData.getId().getDocumentProject().getId()); + assertEquals("project name", documentData.getId().getDocumentProject().getName()); + assertEquals("wiki page id", documentData.getId().getDocumentId()); + assertEquals(DocumentType.WIKI_PAGE, documentData.getType()); + assertEquals("wiki page title", documentData.getTitle()); + assertNull(documentData.getContent()); + assertNotNull(documentData.getBaseline()); + assertEquals("pb. projectBaselineName | db. documentBaselineName", documentData.getBaseline().asPlaceholder()); + assertNotNull(uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline()); + assertEquals("pb. projectBaselineName | db. documentBaselineName", uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline().asPlaceholder()); + assertNull(documentData.getRevision()); + assertEquals("12345", documentData.getLastRevision()); + assertNull(documentData.getContent()); + + ExportParams exportParams = ExportParams.builder() + .locationPath("location path") + .build(); + + try ( + MockedConstruction wikiRendererMockedConstruction = mockConstruction(WikiRenderer.class, (mock, context) -> { + when(mock.render(any(), any(), any())).thenReturn("test content"); + }) + ) { + DocumentData documentDataWithContent = uniqueObjectConverter + .withContent(true) + .withExportParams(exportParams) + .toDocumentData(); + assertEquals("test content", documentDataWithContent.getContent()); + } + } + + @Test + void testWikiPageInDefaultRepoDocumentData() { + when(wikiPageInDefaultRepo.getId()).thenReturn("wiki page id"); + when(wikiPageInDefaultRepo.getLastRevision()).thenReturn("12345"); + when(wikiPageInDefaultRepo.getProject()).thenReturn(null); + when(wikiPageInDefaultRepo.getTitleOrName()).thenReturn("wiki page title"); + + UniqueObjectConverter uniqueObjectConverter = new UniqueObjectConverter(wikiPageInDefaultRepo); + DocumentData documentData = uniqueObjectConverter.toDocumentData(); + + assertNull(documentData.getId().getDocumentProject()); + assertEquals("wiki page id", documentData.getId().getDocumentId()); + assertEquals(DocumentType.WIKI_PAGE, documentData.getType()); + assertEquals("wiki page title", documentData.getTitle()); + assertNull(documentData.getContent()); + assertNotNull(documentData.getBaseline()); + assertEquals("", documentData.getBaseline().asPlaceholder()); + assertNotNull(uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline()); + assertEquals("", uniqueObjectConverter.getUniqueObjectAdapter().getDocumentBaseline().asPlaceholder()); + assertNull(documentData.getRevision()); + assertEquals("12345", documentData.getLastRevision()); + assertNull(documentData.getContent()); + + ExportParams exportParams = ExportParams.builder() + .locationPath("location path") + .build(); + + try ( + MockedConstruction wikiRendererMockedConstruction = mockConstruction(WikiRenderer.class, (mock, context) -> { + when(mock.render(any(), any(), any())).thenReturn("test content"); + }) + ) { + DocumentData documentDataWithContent = uniqueObjectConverter + .withContent(true) + .withExportParams(exportParams) + .toDocumentData(); + assertEquals("test content", documentDataWithContent.getContent()); + } + } + + @Test + void testBaselineCollectionDocumentData() { + assertThrows(IllegalArgumentException.class, () -> new UniqueObjectConverter(baselineCollection)); + } +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/ModelObjectProviderTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/ModelObjectProviderTest.java new file mode 100644 index 00000000..d3d70ab6 --- /dev/null +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/ModelObjectProviderTest.java @@ -0,0 +1,277 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents; + +import ch.sbb.polarion.extension.generic.exception.ObjectNotFoundException; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; +import ch.sbb.polarion.extension.generic.test_extensions.CustomExtensionMock; +import ch.sbb.polarion.extension.generic.test_extensions.TransactionalExecutorExtension; +import com.polarion.alm.projects.model.IProject; +import com.polarion.alm.shared.api.model.ModelObject; +import com.polarion.alm.shared.api.model.document.Document; +import com.polarion.alm.shared.api.model.document.DocumentSelector; +import com.polarion.alm.shared.api.model.document.internal.InternalDocuments; +import com.polarion.alm.shared.api.model.rp.RichPage; +import com.polarion.alm.shared.api.model.rp.RichPageSelector; +import com.polarion.alm.shared.api.model.rp.internal.InternalRichPages; +import com.polarion.alm.shared.api.model.tr.TestRun; +import com.polarion.alm.shared.api.model.tr.TestRunSelector; +import com.polarion.alm.shared.api.model.tr.internal.InternalTestRuns; +import com.polarion.alm.shared.api.model.wiki.WikiPage; +import com.polarion.alm.shared.api.model.wiki.WikiPageSelector; +import com.polarion.alm.shared.api.model.wiki.WikiPages; +import com.polarion.alm.shared.api.transaction.TransactionalExecutor; +import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Map; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +@ExtendWith({MockitoExtension.class, TransactionalExecutorExtension.class}) +class ModelObjectProviderTest { + + @CustomExtensionMock + private InternalReadOnlyTransaction internalReadOnlyTransactionMock; + + @Mock + private PdfExporterPolarionService pdfExporterPolarionService; + + @BeforeEach + void setUp() { + IProject projectMock = mock(IProject.class); + lenient().when(projectMock.getId()).thenReturn("testProjectId"); + lenient().when(pdfExporterPolarionService.getProject(eq("testProjectId"))).thenReturn(projectMock); + lenient().when(pdfExporterPolarionService.getProject(eq("nonExistingProjectId"))).thenThrow(new ObjectNotFoundException("Project not found")); + } + + public static Stream paramsForModelObjectProviderGetDocument() { + return Stream.of( + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .locationPath("_default/testLocationPath") + .documentType(DocumentType.LIVE_DOC) + .build()), + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .locationPath("_default/testLocationPath") + .revision("12345") + .documentType(DocumentType.LIVE_DOC) + .build()) + ); + } + + @ParameterizedTest + @MethodSource("paramsForModelObjectProviderGetDocument") + void testModelObjectProviderGetDocument(@NotNull ExportParams exportParams, ExtensionContext extensionContext) { + InternalDocuments internalDocumentsMock = mock(InternalDocuments.class); + DocumentSelector documentSelectorMock = mock(DocumentSelector.class); + when(documentSelectorMock.revision(any())).thenReturn(documentSelectorMock); + Document documentMock = mock(Document.class); + when(documentSelectorMock.spaceReferenceAndName(any(), any())).thenReturn(documentMock); + when(internalDocumentsMock.getBy()).thenReturn(documentSelectorMock); + when(internalReadOnlyTransactionMock.documents()).thenReturn(internalDocumentsMock); + + ModelObjectProvider modelObjectProvider = new ModelObjectProvider(exportParams, pdfExporterPolarionService); + ModelObject modelObject = TransactionalExecutor.executeSafelyInReadOnlyTransaction(modelObjectProvider::getModelObject); + + assertEquals(documentMock, modelObject); + } + + public static Stream paramsForModelObjectProviderGetRichPage() { + return Stream.of( + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .locationPath("testLocationPath") + .documentType(DocumentType.LIVE_REPORT) + .build()), + Arguments.of(ExportParams.builder() + .locationPath("testLocationPath") + .documentType(DocumentType.LIVE_REPORT) + .build()), + Arguments.of(ExportParams.builder() + .locationPath("testLocationPath") + .revision("12345") + .documentType(DocumentType.LIVE_REPORT) + .build()) + ); + } + + @ParameterizedTest + @MethodSource("paramsForModelObjectProviderGetRichPage") + void testModelObjectProviderGetRichPage(@NotNull ExportParams exportParams, ExtensionContext extensionContext) { + InternalRichPages richPagesMock = mock(InternalRichPages.class); + RichPageSelector richPagesSelectorMock = mock(RichPageSelector.class); + when(richPagesSelectorMock.revision(any())).thenReturn(richPagesSelectorMock); + RichPage richPageMock = mock(RichPage.class); + when(richPagesSelectorMock.spaceReferenceAndName(any(), any())).thenReturn(richPageMock); + when(richPagesMock.getBy()).thenReturn(richPagesSelectorMock); + when(internalReadOnlyTransactionMock.richPages()).thenReturn(richPagesMock); + + ModelObjectProvider modelObjectProvider = new ModelObjectProvider(exportParams, pdfExporterPolarionService); + ModelObject modelObject = TransactionalExecutor.executeSafelyInReadOnlyTransaction(modelObjectProvider::getModelObject); + + assertEquals(richPageMock, modelObject); + } + + public static Stream paramsForModelObjectProviderGetTestRun() { + return Stream.of( + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .urlQueryParameters(Map.of("id", "testRunId")) + .documentType(DocumentType.TEST_RUN) + .build()), + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .urlQueryParameters(Map.of("id", "testRunId")) + .revision("12345") + .documentType(DocumentType.TEST_RUN) + .build()) + ); + } + + @ParameterizedTest + @MethodSource("paramsForModelObjectProviderGetTestRun") + void testModelObjectProviderGetTestRun(@NotNull ExportParams exportParams, ExtensionContext extensionContext) { + InternalTestRuns testRunsMock = mock(InternalTestRuns.class); + TestRunSelector testRunsSelectorMock = mock(TestRunSelector.class); + when(testRunsSelectorMock.revision(any())).thenReturn(testRunsSelectorMock); + TestRun testRunMock = mock(TestRun.class); + when(testRunsSelectorMock.ids(any(), any())).thenReturn(testRunMock); + when(testRunsMock.getBy()).thenReturn(testRunsSelectorMock); + when(internalReadOnlyTransactionMock.testRuns()).thenReturn(testRunsMock); + + ModelObjectProvider modelObjectProvider = new ModelObjectProvider(exportParams, pdfExporterPolarionService); + ModelObject modelObject = TransactionalExecutor.executeSafelyInReadOnlyTransaction(modelObjectProvider::getModelObject); + + assertEquals(testRunMock, modelObject); + } + + public static Stream paramsForModelObjectProviderGetWikiPage() { + return Stream.of( + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .locationPath("_default/testLocationPath") + .documentType(DocumentType.WIKI_PAGE) + .build()), + Arguments.of(ExportParams.builder() + .locationPath("_default/testLocationPath") + .documentType(DocumentType.WIKI_PAGE) + .build()), + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .locationPath("_default/testLocationPath") + .revision("12345") + .documentType(DocumentType.WIKI_PAGE) + .build()) + ); + } + + @ParameterizedTest + @MethodSource("paramsForModelObjectProviderGetWikiPage") + void testModelObjectProviderGetWikiPage(@NotNull ExportParams exportParams, ExtensionContext extensionContext) { + WikiPages wikiPagesMock = mock(WikiPages.class); + WikiPageSelector wikiPagesSelectorMock = mock(WikiPageSelector.class); + when(wikiPagesSelectorMock.revision(any())).thenReturn(wikiPagesSelectorMock); + WikiPage wikiPageMock = mock(WikiPage.class); + when(wikiPagesSelectorMock.spaceReferenceAndName(any(), any())).thenReturn(wikiPageMock); + when(wikiPagesMock.getBy()).thenReturn(wikiPagesSelectorMock); + when(internalReadOnlyTransactionMock.wikiPages()).thenReturn(wikiPagesMock); + + ModelObjectProvider modelObjectProvider = new ModelObjectProvider(exportParams, pdfExporterPolarionService); + ModelObject modelObject = TransactionalExecutor.executeSafelyInReadOnlyTransaction(modelObjectProvider::getModelObject); + + assertEquals(wikiPageMock, modelObject); + } + + public static Stream paramsForModelObjectProviderShouldFail() { + return Stream.of( + Arguments.of(ExportParams.builder() + .projectId("nonExistingProjectId") + .locationPath("_default/testLocationPath") + .documentType(DocumentType.LIVE_DOC) + .build(), ObjectNotFoundException.class), + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .documentType(DocumentType.LIVE_DOC) + .build(), IllegalArgumentException.class), +// Arguments.of(ExportParams.builder() +// .projectId("testProjectId") +// .locationPath("wrongLocationPath") +// .documentType(DocumentType.LIVE_DOC) +// .build(), IllegalArgumentException.class), +// Arguments.of(ExportParams.builder() +// .projectId("testProjectId") +// .locationPath("_default/nonExistingLocationPath") +// .documentType(DocumentType.LIVE_DOC) +// .build(), IllegalArgumentException.class), + + Arguments.of(ExportParams.builder() + .projectId("nonExistingProjectId") + .locationPath("_default/testLocationPath") + .documentType(DocumentType.LIVE_REPORT) + .build(), ObjectNotFoundException.class), + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .documentType(DocumentType.LIVE_REPORT) + .build(), IllegalArgumentException.class), + + Arguments.of(ExportParams.builder() + .projectId("nonExistingProjectId") + .urlQueryParameters(Map.of("id", "testRunId")) + .documentType(DocumentType.TEST_RUN) + .build(), ObjectNotFoundException.class), + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .documentType(DocumentType.TEST_RUN) + .build(), IllegalArgumentException.class), + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .urlQueryParameters(Map.of()) + .documentType(DocumentType.TEST_RUN) + .build(), IllegalArgumentException.class), + + Arguments.of(ExportParams.builder() + .projectId("nonExistingProjectId") + .locationPath("_default/testLocationPath") + .documentType(DocumentType.WIKI_PAGE) + .build(), ObjectNotFoundException.class), + Arguments.of(ExportParams.builder() + .projectId("testProjectId") + .documentType(DocumentType.WIKI_PAGE) + .build(), IllegalArgumentException.class) + ); + + } + + @ParameterizedTest + @MethodSource("paramsForModelObjectProviderShouldFail") + void testModelObjectProviderShouldFail(@NotNull ExportParams exportParams, @NotNull Class expectedExceptionClass) { + ModelObjectProvider modelObjectProvider = new ModelObjectProvider(exportParams, pdfExporterPolarionService); + assertThrows(expectedExceptionClass, () -> TransactionalExecutor.executeSafelyInReadOnlyTransaction(modelObjectProvider::getModelObject)); + } + + @Test + void testModelObjectProviderGetBaselineCollection() { + ExportParams exportParams = ExportParams.builder() + .documentType(DocumentType.BASELINE_COLLECTION) + .build(); + ModelObjectProvider modelObjectProvider = new ModelObjectProvider(exportParams, pdfExporterPolarionService); + + assertThrows(IllegalArgumentException.class, () -> TransactionalExecutor.executeSafelyInReadOnlyTransaction(modelObjectProvider::getModelObject)); + } +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/UniqueObjectConverterTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/UniqueObjectConverterTest.java new file mode 100644 index 00000000..c2bf4c32 --- /dev/null +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/UniqueObjectConverterTest.java @@ -0,0 +1,48 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents; + +import com.polarion.alm.shared.api.model.document.Document; +import com.polarion.alm.shared.api.model.rp.RichPage; +import com.polarion.alm.shared.api.model.tr.TestRun; +import com.polarion.alm.shared.api.model.wiki.WikiPage; +import com.polarion.alm.tracker.model.IModule; +import com.polarion.alm.tracker.model.IRichPage; +import com.polarion.alm.tracker.model.ITestRun; +import com.polarion.alm.tracker.model.IWikiPage; +import org.junit.jupiter.api.Test; + +import static org.mockito.Mockito.*; + +class UniqueObjectConverterTest { + + @Test + void testDocument() { + Document document = mock(Document.class); + when(document.getOldApi()).thenReturn(mock(IModule.class)); + new UniqueObjectConverter(document); + verify(document, times(1)).getOldApi(); + } + + @Test + void testRichPage() { + RichPage richPage = mock(RichPage.class); + when(richPage.getOldApi()).thenReturn(mock(IRichPage.class)); + new UniqueObjectConverter(richPage); + verify(richPage, times(1)).getOldApi(); + } + + @Test + void testTestRun() { + TestRun testRun = mock(TestRun.class); + when(testRun.getOldApi()).thenReturn(mock(ITestRun.class)); + new UniqueObjectConverter(testRun); + verify(testRun, times(1)).getOldApi(); + } + + @Test + void testWikiPage() { + WikiPage wikiPage = mock(WikiPage.class); + when(wikiPage.getOldApi()).thenReturn(mock(IWikiPage.class)); + new UniqueObjectConverter(wikiPage); + verify(wikiPage, times(1)).getOldApi(); + } +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveDocGetRevisionPlaceholderTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveDocGetRevisionPlaceholderTest.java new file mode 100644 index 00000000..0d1af9f1 --- /dev/null +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/rest/model/documents/adapters/LiveDocGetRevisionPlaceholderTest.java @@ -0,0 +1,38 @@ +package ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.adapters; + +import com.polarion.alm.tracker.model.IModule; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class LiveDocGetRevisionPlaceholderTest { + + private static Stream getRevisionPlaceholderParameters() { + return Stream.of( + Arguments.of(null, null, "lastRevision", "lastRevision"), + Arguments.of("revision", null, "lastRevision", "revision"), + Arguments.of("revision", "customFieldRevision", "lastRevision", "customFieldRevision"), + Arguments.of(null, "customFieldRevision", "lastRevision", "customFieldRevision") + ); + } + + @ParameterizedTest + @MethodSource("getRevisionPlaceholderParameters") + void testGetRevisionPlaceholder(String revision, String customFieldRevision, String lastRevision, String expectedRevisionPlaceholder) { + IModule module = mock(IModule.class); + when(module.getRevision()).thenReturn(revision); + when(module.getLastRevision()).thenReturn(lastRevision); + when(module.getCustomField("docRevision")).thenReturn(customFieldRevision); + + LiveDocAdapter liveDocAdapter = new LiveDocAdapter(module); + String revisionPlaceholder = liveDocAdapter.getRevisionPlaceholder(); + + assertEquals(expectedRevisionPlaceholder, revisionPlaceholder); + } +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/service/PdfExporterPolarionServiceTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/service/PdfExporterPolarionServiceTest.java index 718ebe48..213e6145 100644 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/service/PdfExporterPolarionServiceTest.java +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/service/PdfExporterPolarionServiceTest.java @@ -5,7 +5,6 @@ import ch.sbb.polarion.extension.generic.settings.SettingName; import ch.sbb.polarion.extension.generic.util.PObjectListStub; import ch.sbb.polarion.extension.generic.util.ScopeUtils; -import ch.sbb.polarion.extension.pdf_exporter.exception.BaselineExecutionException; import ch.sbb.polarion.extension.pdf_exporter.rest.model.attachments.TestRunAttachment; import ch.sbb.polarion.extension.pdf_exporter.rest.model.collections.DocumentCollectionEntry; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.stylepackage.StylePackageModel; @@ -15,8 +14,6 @@ import com.polarion.alm.shared.api.model.baselinecollection.BaselineCollection; import com.polarion.alm.shared.api.model.baselinecollection.BaselineCollectionReference; import com.polarion.alm.shared.api.transaction.ReadOnlyTransaction; -import com.polarion.alm.shared.api.utils.PolarionUtils; -import com.polarion.alm.shared.api.utils.RunnableWithResult; import com.polarion.alm.tracker.ITestManagementService; import com.polarion.alm.tracker.ITrackerService; import com.polarion.alm.tracker.model.IModule; @@ -29,8 +26,6 @@ import com.polarion.platform.security.ISecurityService; import com.polarion.platform.service.repository.IRepositoryService; import com.polarion.subterra.base.location.ILocation; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.MockedConstruction; @@ -307,41 +302,4 @@ void testGetDocumentsFromCollection() { } } - @Test - void testExecuteInBaseline() { - PolarionUtils polarionUtils = new PolarionUtils() { - @Override - public @Nullable T executeInBaseline(@NotNull String s, @NotNull RunnableWithResult runnableWithResult) { - return runnableWithResult.run(); - } - - @Override - public @Nullable T executeOutsideBaseline(@NotNull RunnableWithResult runnableWithResult) { - return null; - } - - @Override - public @NotNull String convertToAscii(@Nullable String s) { - return ""; - } - - @Override - public @NotNull String convertToAscii(@Nullable String s, @Nullable String s1) { - return ""; - } - }; - - ReadOnlyTransaction mockReadOnlyTransaction = mock(ReadOnlyTransaction.class); - when(mockReadOnlyTransaction.utils()).thenReturn(polarionUtils); - - assertEquals("valueWithoutBaseline", service.executeInBaseline(null, mockReadOnlyTransaction, () -> "valueWithoutBaseline")); - - assertEquals("valueInBaseline", service.executeInBaseline("1234", mockReadOnlyTransaction, () -> "valueInBaseline")); - assertThrows(BaselineExecutionException.class, () -> service.executeInBaseline("5678", mockReadOnlyTransaction, this::testCallable)); - } - - private String testCallable() throws Exception { - throw new Exception("argument"); - } - } diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/service/PolarionBaselineExecutorTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/service/PolarionBaselineExecutorTest.java new file mode 100644 index 00000000..c59e9f6f --- /dev/null +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/service/PolarionBaselineExecutorTest.java @@ -0,0 +1,38 @@ +package ch.sbb.polarion.extension.pdf_exporter.service; + +import ch.sbb.polarion.extension.pdf_exporter.exception.BaselineExecutionException; +import ch.sbb.polarion.extension.generic.test_extensions.CustomExtensionMock; +import ch.sbb.polarion.extension.generic.test_extensions.TransactionalExecutorExtension; +import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith({TransactionalExecutorExtension.class}) +class PolarionBaselineExecutorTest { + + @CustomExtensionMock + private InternalReadOnlyTransaction internalReadOnlyTransactionMock; + + @Test + void testExecuteInBaseline() { + assertEquals("valueWithoutBaseline", PolarionBaselineExecutor.executeInBaseline(null, internalReadOnlyTransactionMock, () -> "valueWithoutBaseline")); + + assertEquals("valueInBaseline", PolarionBaselineExecutor.executeInBaseline("1234", internalReadOnlyTransactionMock, () -> "valueInBaseline")); + assertThrows(BaselineExecutionException.class, () -> PolarionBaselineExecutor.executeInBaseline("5678", internalReadOnlyTransactionMock, this::testCallableWithException)); + assertThrows(NullPointerException.class, () -> PolarionBaselineExecutor.executeInBaseline("5678", internalReadOnlyTransactionMock, this::testCallableWithRuntimeException)); + } + + private String testCallableWithException() throws IOException { + throw new IOException("io exception"); + } + + private String testCallableWithRuntimeException() { + throw new NullPointerException("null pointer exception"); + } + +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/test_extensions/DocumentDataFactoryMockExtension.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/test_extensions/DocumentDataFactoryMockExtension.java new file mode 100644 index 00000000..4867b85e --- /dev/null +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/test_extensions/DocumentDataFactoryMockExtension.java @@ -0,0 +1,51 @@ +package ch.sbb.polarion.extension.pdf_exporter.test_extensions; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; +import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataFactory; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.mockito.MockedStatic; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.Mockito.*; + +public class DocumentDataFactoryMockExtension implements BeforeEachCallback, AfterEachCallback { + + private MockedStatic documentDataFactoryMockedStatic; + private static final Map> documentDataMocks = new HashMap<>(); + + @Override + public void beforeEach(ExtensionContext context) throws Exception { + documentDataFactoryMockedStatic = mockStatic(DocumentDataFactory.class); + + documentDataFactoryMockedStatic.when(() -> DocumentDataFactory.getDocumentData(any(ExportParams.class), anyBoolean())).thenAnswer(invocation -> { + ExportParams params = invocation.getArgument(0); + DocumentData value = documentDataMocks.get(params); + if (value != null) { + return value; + } else { + throw new IllegalArgumentException("No mock registered for given ExportParams: " + params); + } + }); + } + + public void register(ExportParams exportParams, DocumentData mock) { + if (documentDataMocks.containsKey(exportParams)) { + throw new IllegalStateException("Mock already registered for given ExportParams: " + exportParams); + } + documentDataMocks.put(exportParams, mock); + } + + @Override + public void afterEach(ExtensionContext context) throws Exception { + if (documentDataFactoryMockedStatic != null) { + documentDataFactoryMockedStatic.close(); + } + documentDataMocks.clear(); + } + +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/CustomResourceUrlResolverTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/CustomResourceUrlResolverTest.java index 4e5c19df..9a65a147 100644 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/CustomResourceUrlResolverTest.java +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/CustomResourceUrlResolverTest.java @@ -8,10 +8,10 @@ import java.io.InputStream; import java.net.URL; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; -import static org.mockito.Mockito.times; @ExtendWith(MockitoExtension.class) class CustomResourceUrlResolverTest { @@ -30,4 +30,4 @@ void replaceImagesUrlUnderscoreAndSpaceReplacementTest() { } } } -} \ No newline at end of file +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataFactoryTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataFactoryTest.java new file mode 100644 index 00000000..272447ec --- /dev/null +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataFactoryTest.java @@ -0,0 +1,109 @@ +package ch.sbb.polarion.extension.pdf_exporter.util; + +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.ModelObjectProvider; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveDocId; +import ch.sbb.polarion.extension.pdf_exporter.service.PdfExporterPolarionService; +import ch.sbb.polarion.extension.generic.test_extensions.CustomExtensionMock; +import ch.sbb.polarion.extension.generic.test_extensions.PlatformContextMockExtension; +import ch.sbb.polarion.extension.generic.test_extensions.TransactionalExecutorExtension; +import com.polarion.alm.projects.IProjectService; +import com.polarion.alm.projects.model.IProject; +import com.polarion.alm.projects.model.IUniqueObject; +import com.polarion.alm.shared.api.model.document.Document; +import com.polarion.alm.shared.api.model.document.DocumentSelector; +import com.polarion.alm.shared.api.model.document.internal.InternalDocuments; +import com.polarion.alm.shared.api.services.internal.InternalServices; +import com.polarion.alm.shared.api.transaction.internal.InternalReadOnlyTransaction; +import com.polarion.alm.tracker.ITrackerService; +import com.polarion.alm.tracker.model.ITrackerProject; +import com.polarion.alm.tracker.model.ipi.IInternalBaselinesManager; +import com.polarion.alm.tracker.spi.model.IInternalModule; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith({MockitoExtension.class, TransactionalExecutorExtension.class, PlatformContextMockExtension.class}) +class DocumentDataFactoryTest { + + @CustomExtensionMock + private InternalReadOnlyTransaction internalReadOnlyTransactionMock; + + @CustomExtensionMock + private IProjectService projectServiceMock; + + @Mock + PdfExporterPolarionService pdfExporterPolarionServiceMock; + + @BeforeEach + void setUp() { + IProject projectMock = mock(IProject.class); + when(projectMock.getId()).thenReturn("testProjectId"); + when(pdfExporterPolarionServiceMock.getProject("testProjectId")).thenReturn(projectMock); + + InternalDocuments internalDocumentsMock = mock(InternalDocuments.class); + DocumentSelector documentSelectorMock = mock(DocumentSelector.class); + when(documentSelectorMock.revision(ArgumentMatchers.any())).thenReturn(documentSelectorMock); + Document documentMock = mock(Document.class); + when(documentSelectorMock.spaceReferenceAndName(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(documentMock); + when(internalDocumentsMock.getBy()).thenReturn(documentSelectorMock); + when(internalReadOnlyTransactionMock.documents()).thenReturn(internalDocumentsMock); + } + + @Test + void testGetDocumentData() { + IInternalModule moduleMock = mock(IInternalModule.class); + when(moduleMock.getId()).thenReturn("testModuleId"); + when(moduleMock.getModuleFolder()).thenReturn("testModuleFolder"); + when(moduleMock.getTitleOrName()).thenReturn("testModuleTitle"); + ITrackerProject projectMock = mock(ITrackerProject.class); + when(projectMock.getId()).thenReturn("testProjectId"); + when(moduleMock.getProject()).thenReturn(projectMock); + when(moduleMock.getLastRevision()).thenReturn("12345"); + + IInternalBaselinesManager internalBaselinesManager = mock(IInternalBaselinesManager.class); + when(projectMock.getBaselinesManager()).thenReturn(internalBaselinesManager); + when(internalBaselinesManager.getRevisionBaseline("12345")).thenReturn(null); + + InternalServices internalServicesMock = mock(InternalServices.class); + ITrackerService trackerService = mock(ITrackerService.class); + when(trackerService.getTrackerProject(any(IProject.class))).thenReturn(projectMock); + lenient().when(internalServicesMock.trackerService()).thenReturn(trackerService); + lenient().when(internalReadOnlyTransactionMock.services()).thenReturn(internalServicesMock); + + Document documentMock = mock(Document.class); + when(documentMock.getOldApi()).thenReturn(moduleMock); + + when(projectServiceMock.getProject("testProjectId")).thenReturn(projectMock); + + ExportParams exportParamsMock = ExportParams.builder() + .projectId("testProjectId") + .locationPath("testModuleFolder/testLocationPath") + .documentType(DocumentType.LIVE_DOC) + .build(); + when(new ModelObjectProvider(exportParamsMock, pdfExporterPolarionServiceMock).getModelObject(internalReadOnlyTransactionMock)) + .thenReturn(documentMock); + + DocumentData actualDocumentData = DocumentDataFactory.getDocumentData(exportParamsMock, false); + + assertNotNull(actualDocumentData); + assertEquals("testProjectId", actualDocumentData.getId().getDocumentProject().getId()); + assertEquals("testModuleFolder", ((LiveDocId) actualDocumentData.getId()).getSpaceId()); + assertEquals("testModuleId", actualDocumentData.getId().getDocumentId()); + assertEquals(DocumentType.LIVE_DOC, actualDocumentData.getType()); + assertEquals("testModuleTitle", actualDocumentData.getTitle()); + assertNull(actualDocumentData.getRevision()); + assertEquals("12345", actualDocumentData.getLastRevision()); + assertEquals("12345", actualDocumentData.getRevisionPlaceholder()); + assertEquals("", actualDocumentData.getBaseline().asPlaceholder()); + assertNull(actualDocumentData.getContent()); + } +} diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataHelperTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataHelperTest.java deleted file mode 100644 index e28d24ee..00000000 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentDataHelperTest.java +++ /dev/null @@ -1,68 +0,0 @@ -package ch.sbb.polarion.extension.pdf_exporter.util; - -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; -import com.polarion.alm.tracker.model.IModule; -import com.polarion.subterra.base.location.ILocation; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class DocumentDataHelperTest { - private DocumentDataHelper documentDataHelper; - - @BeforeEach - public void setup() { - documentDataHelper = new DocumentDataHelper(null); - } - - @ParameterizedTest - @MethodSource("getDocumentStatusParameters") - void shouldGetDocumentStatus(String revision, String customFieldRevision, String lastRevision, String expectedStatus) { - IModule module = mock(IModule.class); - DocumentData documentData = DocumentData.builder(DocumentType.LIVE_DOC, module) - .id("testId") - .title("testTitle") - .lastRevision(lastRevision) - .build(); - when(module.getCustomField("docRevision")).thenReturn(customFieldRevision); - - String documentStatus = documentDataHelper.getDocumentStatus(revision, documentData); - assertThat(documentStatus).isEqualTo(expectedStatus); - } - - private static Stream getDocumentStatusParameters() { - return Stream.of( - Arguments.of("revision", "customFieldRevision", "lastRevision", "revision"), - Arguments.of(null, "customFieldRevision", "lastRevision", "customFieldRevision"), - Arguments.of(null, null, "lastRevision", "lastRevision")); - } - - - @ParameterizedTest - @MethodSource("getDocumentLocationParameters") - void shouldGetDocumentLocation(String location, String revision) { - ILocation documentLocation = documentDataHelper.getDocumentLocation(location, revision); - assertThat(documentLocation.getLocationPath()).isEqualTo(location); - assertThat(documentLocation.getRevision()).isEqualTo(revision); - } - - @Test - void shouldCreatePath() { - assertThat(documentDataHelper.createPath("testProjectId", "testLocationPath")).isEqualTo("testProjectId/testLocationPath"); - } - - private static Stream getDocumentLocationParameters() { - return Stream.of( - Arguments.of("testLocation", "testRevision"), - Arguments.of("testLocation", null)); - } -} \ No newline at end of file diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentFileNameHelperTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentFileNameHelperTest.java index d9f5b1a9..bdeb16e6 100644 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentFileNameHelperTest.java +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/DocumentFileNameHelperTest.java @@ -1,36 +1,58 @@ package ch.sbb.polarion.extension.pdf_exporter.util; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; +import ch.sbb.polarion.extension.generic.context.CurrentContextExtension; +import ch.sbb.polarion.extension.generic.settings.NamedSettingsRegistry; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentProject; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveDocId; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.filename.FileNameTemplateModel; +import ch.sbb.polarion.extension.pdf_exporter.settings.FileNameTemplateSettings; +import ch.sbb.polarion.extension.pdf_exporter.test_extensions.DocumentDataFactoryMockExtension; +import ch.sbb.polarion.extension.generic.test_extensions.PlatformContextMockExtension; +import ch.sbb.polarion.extension.generic.test_extensions.TransactionalExecutorExtension; import ch.sbb.polarion.extension.pdf_exporter.util.velocity.VelocityEvaluator; import com.polarion.alm.tracker.model.IModule; +import com.polarion.alm.tracker.model.baselinecollection.IBaselineCollection; 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 java.util.List; + import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; -@ExtendWith(MockitoExtension.class) +@ExtendWith({ + MockitoExtension.class, + TransactionalExecutorExtension.class, + PlatformContextMockExtension.class, + CurrentContextExtension.class, + DocumentDataFactoryMockExtension.class +}) class DocumentFileNameHelperTest { + @Mock - VelocityEvaluator velocityEvaluator; + private VelocityEvaluator velocityEvaluator; + + @InjectMocks + private DocumentFileNameHelper fileNameHelper; @InjectMocks - DocumentFileNameHelper fileNameHelper; + private DocumentDataFactoryMockExtension documentDataFactoryMockExtension; @Test void evaluateVelocity() { - DocumentData documentData = DocumentData.builder(DocumentType.LIVE_DOC, mock(IModule.class)) - .id("Test Id") + DocumentData documentData = DocumentData.creator(DocumentType.LIVE_DOC, mock(IModule.class)) + .id(new LiveDocId(new DocumentProject("testProjectId", "Test Project"), "testSpaceId", "testDocumentId")) .title("Test Title") - .projectName("Test Project") + .lastRevision("12345") + .revisionPlaceholder("12345") .build(); FileNameTemplateModel settingOneModel = FileNameTemplateModel.builder() .documentNameTemplate("$projectName $document.moduleFolder $document.moduleName") @@ -39,7 +61,7 @@ void evaluateVelocity() { when(velocityEvaluator.evaluateVelocityExpressions(eq(documentData), anyString())).thenAnswer(a -> a.getArguments()[1]); String result = fileNameHelper.evaluateVelocity(documentData, settingOneModel.getDocumentNameTemplate()); - assertThat(result).contains("pdf"); + assertThat(result).endsWith(".pdf"); } @Test @@ -50,8 +72,7 @@ void getDocumentFileNameWithMissingProjectIdForLiveDocOrTestRun() { .documentType(DocumentType.LIVE_DOC) .build(); // Act & Assert - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> - fileNameHelper.getDocumentFileName(exportParams)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> fileNameHelper.getDocumentFileName(exportParams)); assertEquals("Project ID must be provided for LiveDoc or TestRun export", exception.getMessage()); } @@ -61,13 +82,43 @@ void getDocumentFileNameWithUnsupportedDocumentType() { ExportParams exportParams = ExportParams.builder() .documentType(DocumentType.BASELINE_COLLECTION) .build(); + DocumentData documentDataMock = mock(DocumentData.class); + documentDataFactoryMockExtension.register(exportParams, documentDataMock); // Act & Assert - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> - fileNameHelper.getDocumentFileName(exportParams)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> fileNameHelper.getDocumentFileName(exportParams)); assertEquals("Unsupported document type: BASELINE_COLLECTION", exception.getMessage()); } + @Test + void getDocumentFileName() { + // Arrange + ExportParams exportParams = ExportParams.builder() + .projectId("testProjectId") + .locationPath("testSpaceId/testDocumentId") + .documentType(DocumentType.LIVE_DOC) + .build(); + DocumentData documentData = DocumentData.creator(DocumentType.LIVE_DOC, mock(IModule.class)) + .id(new LiveDocId(new DocumentProject("testProjectId", "Test Project"), "testSpaceId", "testDocumentId")) + .title("Test Title") + .lastRevision("12345") + .revisionPlaceholder("12345") + .build(); + documentDataFactoryMockExtension.register(exportParams, documentData); + + FileNameTemplateSettings fileNameTemplateSettings = new FileNameTemplateSettings(); + FileNameTemplateSettings fileNameTemplateSettingsSpy = spy(fileNameTemplateSettings); + doReturn(fileNameTemplateSettings.defaultValues()).when(fileNameTemplateSettingsSpy).read(anyString(), any(), any()); + + NamedSettingsRegistry.INSTANCE.register(List.of(fileNameTemplateSettingsSpy)); + + when(velocityEvaluator.evaluateVelocityExpressions(eq(documentData), anyString())).thenAnswer(a -> a.getArguments()[1]); + + // Act & Assert + String documentFileName = fileNameHelper.getDocumentFileName(exportParams); + assertThat(documentFileName).endsWith(".pdf"); + } + @Test void getFileNameTemplate() { diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/WildcardUtilsTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/WildcardUtilsTest.java index 61cdc13b..ad44435f 100644 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/WildcardUtilsTest.java +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/util/WildcardUtilsTest.java @@ -6,7 +6,7 @@ import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class WildcardUtilsTest { diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/weasyprint/PdfConverterWeasyPrintTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/weasyprint/PdfConverterWeasyPrintTest.java index e07d95d5..4d9586a5 100644 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/weasyprint/PdfConverterWeasyPrintTest.java +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/weasyprint/PdfConverterWeasyPrintTest.java @@ -2,11 +2,14 @@ import ch.sbb.polarion.extension.pdf_exporter.converter.CoverPageProcessor; import ch.sbb.polarion.extension.pdf_exporter.converter.PdfConverter; -import ch.sbb.polarion.extension.pdf_exporter.rest.model.DocumentData; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.DocumentType; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.ExportParams; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.Orientation; import ch.sbb.polarion.extension.pdf_exporter.rest.model.conversion.PaperSize; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.DocumentData; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.DocumentProject; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.LiveDocId; +import ch.sbb.polarion.extension.pdf_exporter.rest.model.documents.id.WikiPageId; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.coverpage.CoverPageModel; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.css.CssModel; import ch.sbb.polarion.extension.pdf_exporter.rest.model.settings.headerfooter.HeaderFooterModel; @@ -16,7 +19,7 @@ import ch.sbb.polarion.extension.pdf_exporter.settings.CssSettings; import ch.sbb.polarion.extension.pdf_exporter.settings.HeaderFooterSettings; import ch.sbb.polarion.extension.pdf_exporter.settings.LocalizationSettings; -import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataHelper; +import ch.sbb.polarion.extension.pdf_exporter.util.DocumentDataFactory; import ch.sbb.polarion.extension.pdf_exporter.util.FileResourceProvider; import ch.sbb.polarion.extension.pdf_exporter.util.HtmlProcessor; import ch.sbb.polarion.extension.pdf_exporter.util.MediaUtils; @@ -63,10 +66,11 @@ class PdfConverterWeasyPrintTest extends BaseWeasyPrintTest { private MockedStatic completableFutureMockedStatic; private HeaderFooterSettings headerFooterSettings; - private DocumentDataHelper documentDataHelper; private PdfConverter converter; private IModule module; + private MockedStatic documentDataFactoryMockedStatic; + @BeforeEach protected void setUp() { prepareTestMocks(); @@ -80,11 +84,14 @@ protected void setUp() { } return invocation.callRealMethod(); }); + + documentDataFactoryMockedStatic = mockStatic(DocumentDataFactory.class); } @AfterEach protected void tearDown() { completableFutureMockedStatic.close(); + documentDataFactoryMockedStatic.close(); } @SneakyThrows @@ -111,8 +118,6 @@ void prepareTestMocks() { lenient().when(module.getCustomField(anyString())).thenAnswer((Answer) invocation -> "testFieldKey".equals(invocation.getArgument(0)) ? "testFieldValue" : null); - documentDataHelper = mock(DocumentDataHelper.class); - LocalizationSettings localizationSettings = mock(LocalizationSettings.class); when(localizationSettings.load(any(), any())).thenReturn(new LocalizationModel(null, null, null)); @@ -130,7 +135,7 @@ void prepareTestMocks() { WeasyPrintServiceConnector weasyPrintServiceConnector = mock(WeasyPrintServiceConnector.class); when(weasyPrintServiceConnector.convertToPdf(anyString(), any())).thenAnswer((Answer) invocation -> exportToPdf(invocation.getArgument(0), invocation.getArgument(1))); - PlaceholderProcessor placeholderProcessor = new PlaceholderProcessor(pdfExporterPolarionService, documentDataHelper); + PlaceholderProcessor placeholderProcessor = new PlaceholderProcessor(pdfExporterPolarionService); VelocityEvaluator velocityEvaluator = mock(VelocityEvaluator.class); when(velocityEvaluator.evaluateVelocityExpressions(any(), anyString())).thenAnswer(a -> a.getArguments()[1]); @@ -157,7 +162,6 @@ void prepareTestMocks() { pdfExporterPolarionService, headerFooterSettings, cssSettings, - documentDataHelper, placeholderProcessor, velocityEvaluator, coverPageProcessor, @@ -176,14 +180,14 @@ void testConverterSimple() { .paperSize(PaperSize.A4) .build(); - DocumentData liveDoc1 = DocumentData.builder(DocumentType.LIVE_DOC, module) - .id("testId") - .projectName("Test") + DocumentData liveDoc1 = DocumentData.creator(DocumentType.LIVE_DOC, module) + .id(LiveDocId.from("testProjectId", "_default", "testDocumentId")) .title("testTitle") .content("
TEST
") .lastRevision("42") + .revisionPlaceholder("42") .build(); - when(documentDataHelper.getLiveDoc(any(), any())).thenReturn(liveDoc1); + documentDataFactoryMockedStatic.when(() -> DocumentDataFactory.getDocumentData(eq(params), anyBoolean())).thenReturn(liveDoc1); compareContentUsingReferenceImages(getCurrentMethodName(), converter.convertToPdf(params, null)); } @@ -198,14 +202,14 @@ void testConverterComplexWithTitle() { .coverPage("test") .build(); - DocumentData liveDoc2 = DocumentData.builder(DocumentType.LIVE_DOC, module) - .projectName("Test") - .id("testId") + DocumentData liveDoc2 = DocumentData.creator(DocumentType.LIVE_DOC, module) + .id(LiveDocId.from("testProjectId", "_default", "testDocumentId")) .title("testTitle") .content("
TEST page 1
TEST page 2
TEST page 3
") .lastRevision("42") + .revisionPlaceholder("42") .build(); - when(documentDataHelper.getLiveDoc(any(), any())).thenReturn(liveDoc2); + documentDataFactoryMockedStatic.when(() -> DocumentDataFactory.getDocumentData(eq(params), anyBoolean())).thenReturn(liveDoc2); compareContentUsingReferenceImages(getCurrentMethodName(), converter.convertToPdf(params, null)); } @@ -219,13 +223,14 @@ void testConverterSpecialSymbols() { .paperSize(PaperSize.A4) .build(); - DocumentData liveDoc3 = DocumentData.builder(DocumentType.LIVE_DOC, module) - .projectName("Test") - .id("testId") + DocumentData liveDoc3 = DocumentData.creator(DocumentType.LIVE_DOC, module) + .id(LiveDocId.from("testProjectId", "_default", "testDocumentId")) .title("specialSymbolsTitle") + .lastRevision("12345") + .revisionPlaceholder("12345") .content(readHtmlResource("specialSymbols")) .build(); - when(documentDataHelper.getLiveDoc(any(), any())).thenReturn(liveDoc3); + documentDataFactoryMockedStatic.when(() -> DocumentDataFactory.getDocumentData(eq(params), anyBoolean())).thenReturn(liveDoc3); compareContentUsingReferenceImages(getCurrentMethodName(), converter.convertToPdf(params, null)); } @@ -239,13 +244,14 @@ void testConverterSvgImage() { .paperSize(PaperSize.A4) .build(); - DocumentData liveDoc4 = DocumentData.builder(DocumentType.LIVE_DOC, module) - .projectName("Test") - .id("testId") + DocumentData liveDoc4 = DocumentData.creator(DocumentType.LIVE_DOC, module) + .id(LiveDocId.from("testProjectId", "_default", "testDocumentId")) .title("svgImageTitle") + .lastRevision("12345") + .revisionPlaceholder("12345") .content(readHtmlResource("svgImage")) .build(); - when(documentDataHelper.getLiveDoc(any(), any())).thenReturn(liveDoc4); + documentDataFactoryMockedStatic.when(() -> DocumentDataFactory.getDocumentData(eq(params), anyBoolean())).thenReturn(liveDoc4); compareContentUsingReferenceImages(getCurrentMethodName(), converter.convertToPdf(params, null)); } @@ -260,14 +266,14 @@ void testConverterWiki() { .build(); //test wiki page export + {{ REVISION }} placeholder usage - DocumentData wikiPage = DocumentData.builder(DocumentType.LIVE_DOC, mock(IWikiPage.class)) - .projectName("Test") - .id("testId") + DocumentData wikiPage = DocumentData.creator(DocumentType.WIKI_PAGE, mock(IWikiPage.class)) + .id(new WikiPageId(new DocumentProject("testProjectId", "Test Project"), "wikiPageId")) .title("wikiPage") .content("
TEST
") .lastRevision("42") + .revisionPlaceholder("42") .build(); - when(documentDataHelper.getWikiPage(any(), any())).thenReturn(wikiPage); + documentDataFactoryMockedStatic.when(() -> DocumentDataFactory.getDocumentData(eq(params), anyBoolean())).thenReturn(wikiPage); when(headerFooterSettings.load(any(), any())).thenReturn(new HeaderFooterModel("HL", "HC {{ REVISION }}", "HR", "FL", "FC", "FR {{ PAGE_NUMBER }}")); params.setDocumentType(DocumentType.WIKI_PAGE); params.setLocationPath("wikiFolder/wikiPage"); diff --git a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/widgets/BulkPdfExportWidgetRendererTest.java b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/widgets/BulkPdfExportWidgetRendererTest.java index 2df77c7c..be8315ce 100644 --- a/src/test/java/ch/sbb/polarion/extension/pdf_exporter/widgets/BulkPdfExportWidgetRendererTest.java +++ b/src/test/java/ch/sbb/polarion/extension/pdf_exporter/widgets/BulkPdfExportWidgetRendererTest.java @@ -15,9 +15,7 @@ import java.util.List; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock;