From e29bbed556415bacf60f573fbd529104993ac76d Mon Sep 17 00:00:00 2001 From: Anagh Hegde Date: Tue, 21 Nov 2023 13:35:02 +0530 Subject: [PATCH] chore: Add error handling for the community template upload flow (#28948) ## Description When the templates endpoint on cloud services is not reachable from the platform, toasts with a generic error message appear. The messaging needs to be improved to indicate that this owing to the templates (or any other relevant endpoint) on cloud services. #### PR fixes following issue(s) Fixes https://github.com/appsmithorg/appsmith/issues/23196 #### Type of change - Bug fix (non-breaking change which fixes an issue) ## Testing #### How Has This Been Tested? - [ ] Manual - [ ] JUnit #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed --- .../ce/ApplicationTemplateServiceCEImpl.java | 4 +- ...ionTemplateServicePublishTemplateTest.java | 124 ++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationTemplateServicePublishTemplateTest.java diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationTemplateServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationTemplateServiceCEImpl.java index 176dcb6f90..f070ea002d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationTemplateServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationTemplateServiceCEImpl.java @@ -349,7 +349,9 @@ public class ApplicationTemplateServiceCEImpl implements ApplicationTemplateServ .accept(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(payload)) .retrieve() - .bodyToMono(ApplicationTemplate.class); + .bodyToMono(ApplicationTemplate.class) + .onErrorResume(error -> Mono.error(new AppsmithException( + AppsmithError.CLOUD_SERVICES_ERROR, "while publishing template" + error.getMessage()))); } private Mono updateApplicationFlags(String applicationId, String branchId) { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationTemplateServicePublishTemplateTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationTemplateServicePublishTemplateTest.java new file mode 100644 index 0000000000..0aee9ad0f1 --- /dev/null +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationTemplateServicePublishTemplateTest.java @@ -0,0 +1,124 @@ +package com.appsmith.server.services.ce; + +import com.appsmith.server.configurations.CloudServicesConfig; +import com.appsmith.server.domains.Application; +import com.appsmith.server.domains.GitApplicationMetadata; +import com.appsmith.server.domains.Workspace; +import com.appsmith.server.dtos.CommunityTemplateDTO; +import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.services.ApplicationPageService; +import com.appsmith.server.services.ApplicationTemplateService; +import com.appsmith.server.services.WorkspaceService; +import lombok.extern.slf4j.Slf4j; +import mockwebserver3.Dispatcher; +import mockwebserver3.MockResponse; +import mockwebserver3.MockWebServer; +import mockwebserver3.RecordedRequest; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import reactor.test.StepVerifier; + +import java.io.IOException; +import java.time.Instant; +import java.util.List; + +@Slf4j +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class ApplicationTemplateServicePublishTemplateTest { + private static MockWebServer mockCloudServices; + + @Autowired + ApplicationTemplateService applicationTemplateService; + + @Autowired + WorkspaceService workspaceService; + + @Autowired + ApplicationPageService applicationPageService; + + @Autowired + CloudServicesConfig cloudServicesConfig; + + static final Dispatcher dispatcher = new Dispatcher() { + @Override + public MockResponse dispatch(RecordedRequest request) throws InterruptedException { + + switch (request.getPath()) { + case "/api/v1/app-templates/upload-community-template": + return new MockResponse().setResponseCode(500).setBody("Error while uploading template"); + + default: + return new MockResponse() + .setHeader("x-header-name", "header-value") + .setResponseCode(200) + .setBody("response"); + } + } + }; + + @BeforeAll + public static void setUp() throws IOException { + mockCloudServices = new MockWebServer(); + mockCloudServices.setDispatcher(dispatcher); + mockCloudServices.start(); + } + + @AfterAll + public static void tearDown() throws IOException { + mockCloudServices.shutdown(); + } + + private Application setUpTestApplicationForWorkspace(String workspaceId) { + Application testApplication = new Application(); + testApplication.setName("Export-Application-Test-Application"); + testApplication.setWorkspaceId(workspaceId); + testApplication.setUpdatedAt(Instant.now()); + testApplication.setLastDeployedAt(Instant.now()); + testApplication.setModifiedBy("some-user"); + testApplication.setGitApplicationMetadata(new GitApplicationMetadata()); + + cloudServicesConfig.setBaseUrl(String.format("http://localhost:%s", mockCloudServices.getPort())); + + return applicationPageService + .createApplication(testApplication, workspaceId) + .block(); + } + + @Test + @WithUserDetails(value = "api_user") + public void test_application_published_as_community_template() { + // Create Workspace + Workspace workspace = new Workspace(); + workspace.setName("Import-Export-Test-Workspace"); + Workspace savedWorkspace = workspaceService.create(workspace).block(); + + Application testApp = setUpTestApplicationForWorkspace(savedWorkspace.getId()); + CommunityTemplateDTO communityTemplateDTO = new CommunityTemplateDTO(); + communityTemplateDTO.setApplicationId(testApp.getId()); + communityTemplateDTO.setWorkspaceId(testApp.getWorkspaceId()); + communityTemplateDTO.setTitle("Some title"); + communityTemplateDTO.setHeadline("Some headline"); + communityTemplateDTO.setDescription("Some description"); + communityTemplateDTO.setUseCases(List.of("uc1", "uc2")); + communityTemplateDTO.setAuthorEmail("test@user.com"); + + // make sure we've received the response returned by the mockCloudServices + StepVerifier.create(applicationTemplateService.publishAsCommunityTemplate(communityTemplateDTO)) + .expectErrorMatches(throwable -> throwable instanceof AppsmithException + && throwable + .getMessage() + .contains("Received error from cloud services while publishing template")) + .verify(); + + // Test cleanup + applicationPageService.deleteApplication(testApp.getId()).block(); + workspaceService.archiveById(savedWorkspace.getId()).block(); + } +}