chore: First page load time optimization: Introduce server side changes for consolidated API (#29875)

This commit is contained in:
Sumit Kumar 2023-12-29 14:54:38 +05:30 committed by GitHub
parent fdc3502e58
commit c214222cee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1264 additions and 3 deletions

View File

@ -11,7 +11,7 @@ public interface PluginConstants {
String AMAZON_S3_PLUGIN = "amazons3-plugin";
String GOOGLE_SHEETS_PLUGIN = "google-sheets-plugin";
String REST_API_PLUGIN = "restapi-plugin";
String GRAPH_QL_PLUGIN = "graphql-plugin";
String GRAPHQL_PLUGIN = "graphql-plugin";
String OPEN_AI_PLUGIN = "openai-plugin";
String ANTHROPIC_PLUGIN = "anthropic-plugin";
String GOOGLE_AI_PLUGIN = "googleai-plugin";

View File

@ -60,6 +60,7 @@ import static com.appsmith.server.constants.Url.TENANT_URL;
import static com.appsmith.server.constants.Url.THEME_URL;
import static com.appsmith.server.constants.Url.USAGE_PULSE_URL;
import static com.appsmith.server.constants.Url.USER_URL;
import static com.appsmith.server.constants.ce.UrlCE.CONSOLIDATED_API_URL;
import static java.time.temporal.ChronoUnit.DAYS;
@EnableWebFluxSecurity
@ -211,7 +212,8 @@ public class SecurityConfig {
ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, USER_URL + "/resendEmailVerification"),
ServerWebExchangeMatchers.pathMatchers(
HttpMethod.POST, USER_URL + "/verifyEmailVerificationToken"),
ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, PRODUCT_ALERT + "/alert"))
ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, PRODUCT_ALERT + "/alert"),
ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, CONSOLIDATED_API_URL))
.permitAll()
.pathMatchers("/public/**", "/oauth2/**")
.permitAll()

View File

@ -37,6 +37,7 @@ public class UrlCE {
public static final String CUSTOM_JS_LIB_URL = BASE_URL + VERSION + "/libraries";
public static final String PRODUCT_ALERT = BASE_URL + VERSION + "/product-alert";
public static final String SEARCH_ENTITY_URL = BASE_URL + VERSION + "/search-entities";
public static final String CONSOLIDATED_API_URL = BASE_URL + VERSION + "/consolidated-api";
// Sub-paths
public static final String MOCKS = "/mocks";

View File

@ -0,0 +1,54 @@
package com.appsmith.server.controllers;
import com.appsmith.external.views.Views;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.ApplicationMode;
import com.appsmith.server.dtos.ConsolidatedAPIResponseDTO;
import com.appsmith.server.dtos.ResponseDTO;
import com.appsmith.server.services.ConsolidatedAPIService;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@Slf4j
@RestController
@RequestMapping(Url.CONSOLIDATED_API_URL)
public class ConsolidatedAPIController {
private final ConsolidatedAPIService consolidatedAPIService;
public ConsolidatedAPIController(ConsolidatedAPIService consolidatedAPIService) {
this.consolidatedAPIService = consolidatedAPIService;
}
/**
* This endpoint is meant to be used by the client application at the time of 1st page load. Client currently makes
* several API calls to fetch all the required data. This endpoint consolidates all that data and returns them as
* response hence enabling the client to fetch the required data via a single API call only.
*/
@JsonView(Views.Public.class)
@GetMapping
public Mono<ResponseDTO<ConsolidatedAPIResponseDTO>> getAllDataForFirstPageLoad(
@RequestParam(required = false) String applicationId,
@RequestParam(required = false) String defaultPageId,
@RequestParam(required = false) ApplicationMode mode,
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug(
"Going to fetch consolidatedAPI response for applicationId: {}, defaultPageId: {}, branchName: {}, "
+ "mode: {}",
applicationId,
defaultPageId,
branchName,
mode);
return consolidatedAPIService
.getConsolidatedInfoForPageLoad(defaultPageId, applicationId, branchName, mode)
.map(consolidatedAPIResponseDTO ->
new ResponseDTO<>(HttpStatus.OK.value(), consolidatedAPIResponseDTO, null));
}
}

View File

@ -0,0 +1,79 @@
package com.appsmith.server.dtos;
import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.Datasource;
import com.appsmith.server.domains.CustomJSLib;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.domains.Theme;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Map;
/**
* This class serves as a DTO for the response data returned via the consolidated API endpoint call
* (v1/consolidated-api) . Each identifier in the class represents the data returned from a unique endpoint. The
* endpoint info is mentioned on top of each identifier.
*/
@Getter
@Setter
public class ConsolidatedAPIResponseDTO {
/* v1/users/me */
ResponseDTO<UserProfileDTO> v1UsersMeResp;
/* v1/users/features */
ResponseDTO<Map<String, Boolean>> v1UsersFeaturesResp;
/* v1/tenants/current */
ResponseDTO<Tenant> v1TenantsCurrentResp;
/* v1/product-alert/alert */
ResponseDTO<ProductAlertResponseDTO> v1ProductAlertResp;
/* v1/pages */
ResponseDTO<ApplicationPagesDTO> v1PagesResp;
/* v1/actions/view */
ResponseDTO<List<ActionViewDTO>> v1ActionsViewResp;
/* v1/actions */
ResponseDTO<List<ActionDTO>> v1ActionsResp;
/* v1/collections/actions/view */
ResponseDTO<List<ActionCollectionViewDTO>> v1CollectionsActionsViewResp;
/* v1/collections/actions */
ResponseDTO<List<ActionCollectionDTO>> v1CollectionsActionsResp;
/* v1/themes/applications/{applicationId}/current */
ResponseDTO<Theme> v1ThemesApplicationCurrentModeResp;
/* v1/themes/applications/{applicationId} */
ResponseDTO<List<Theme>> v1ThemesResp;
/* v1/pages/{pageId}/view */
ResponseDTO<PageDTO> v1PublishedPageResp;
/* v1/pages/{pageId} */
ResponseDTO<PageDTO> v1PageResp;
/* v1/pages/{pageId} - for all pages */
ResponseDTO<List<PageDTO>> v1PageDSLs;
/* v1/libraries/{applicationId}/view */
ResponseDTO<List<CustomJSLib>> v1LibrariesApplicationResp;
/* v1/plugins */
ResponseDTO<List<Plugin>> v1PluginsResp;
/* v1/datasources */
ResponseDTO<List<Datasource>> v1DatasourcesResp;
/* v1/plugins/{pluginId}/form - for all plugins used in app */
ResponseDTO<Map<String, Map>> v1PluginFormConfigsResp;
/* v1/datasources/mock */
ResponseDTO<List<MockDataSet>> v1DatasourcesMockResp;
}

View File

@ -0,0 +1,10 @@
package com.appsmith.server.services;
import com.appsmith.server.domains.ApplicationMode;
import com.appsmith.server.dtos.ConsolidatedAPIResponseDTO;
import reactor.core.publisher.Mono;
public interface ConsolidatedAPIService {
Mono<ConsolidatedAPIResponseDTO> getConsolidatedInfoForPageLoad(
String defaultPageId, String applicationId, String branchName, ApplicationMode mode);
}

View File

@ -0,0 +1,501 @@
package com.appsmith.server.services;
import com.appsmith.external.exceptions.ErrorDTO;
import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.CreatorContextType;
import com.appsmith.external.models.Datasource;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.datasources.base.DatasourceService;
import com.appsmith.server.domains.ApplicationMode;
import com.appsmith.server.domains.CustomJSLib;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.domains.Theme;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.server.dtos.ActionCollectionViewDTO;
import com.appsmith.server.dtos.ActionViewDTO;
import com.appsmith.server.dtos.ApplicationPagesDTO;
import com.appsmith.server.dtos.ConsolidatedAPIResponseDTO;
import com.appsmith.server.dtos.MockDataDTO;
import com.appsmith.server.dtos.MockDataSet;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.dtos.ProductAlertResponseDTO;
import com.appsmith.server.dtos.ResponseDTO;
import com.appsmith.server.dtos.UserProfileDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.jslibs.base.CustomJSLibService;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.plugins.base.PluginService;
import com.appsmith.server.themes.base.ThemeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.util.Pair;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static com.appsmith.external.constants.PluginConstants.PackageName.GRAPHQL_PLUGIN;
import static com.appsmith.external.constants.PluginConstants.PackageName.REST_API_PLUGIN;
import static com.appsmith.server.constants.ce.FieldNameCE.APPLICATION_ID;
import static com.appsmith.server.constants.ce.FieldNameCE.APP_MODE;
import static com.appsmith.server.constants.ce.FieldNameCE.WORKSPACE_ID;
import static org.apache.commons.lang3.StringUtils.isBlank;
@Slf4j
@Service
public class ConsolidatedAPIServiceImpl implements ConsolidatedAPIService {
private static final String FEATURE_FLAG_RELEASE_SERVER_DSL_MIGRATIONS_ENABLED =
"release_server_dsl_migrations_enabled";
public static final int INTERNAL_SERVER_ERROR_STATUS = AppsmithError.INTERNAL_SERVER_ERROR.getHttpErrorCode();
public static final String INTERNAL_SERVER_ERROR_CODE = AppsmithError.INTERNAL_SERVER_ERROR.getAppErrorCode();
private final SessionUserService sessionUserService;
private final UserService userService;
private final UserDataService userDataService;
private final TenantService tenantService;
private final ProductAlertService productAlertService;
private final NewPageService newPageService;
private final NewActionService newActionService;
private final ActionCollectionService actionCollectionService;
private final ThemeService themeService;
private final ApplicationPageService applicationPageService;
private final CustomJSLibService customJSLibService;
private final PluginService pluginService;
private final ApplicationService applicationService;
private final DatasourceService datasourceService;
private final MockDataService mockDataService;
public ConsolidatedAPIServiceImpl(
SessionUserService sessionUserService,
UserService userService,
UserDataService userDataService,
TenantService tenantService,
ProductAlertService productAlertService,
NewPageService newPageService,
NewActionService newActionService,
ActionCollectionService actionCollectionService,
ThemeService themeService,
ApplicationPageService applicationPageService,
CustomJSLibService customJSLibService,
PluginService pluginService,
ApplicationService applicationService,
DatasourceService datasourceService,
MockDataService mockDataService) {
this.sessionUserService = sessionUserService;
this.userService = userService;
this.userDataService = userDataService;
this.tenantService = tenantService;
this.productAlertService = productAlertService;
this.newPageService = newPageService;
this.newActionService = newActionService;
this.actionCollectionService = actionCollectionService;
this.themeService = themeService;
this.applicationPageService = applicationPageService;
this.customJSLibService = customJSLibService;
this.pluginService = pluginService;
this.applicationService = applicationService;
this.datasourceService = datasourceService;
this.mockDataService = mockDataService;
}
<T> ResponseDTO<T> getSuccessResponse(T data) {
return new ResponseDTO<>(HttpStatus.OK.value(), data, null);
}
<T> Mono<ResponseDTO<T>> getErrorResponseMono(Throwable error, Class<T> type) {
if (error instanceof AppsmithException appsmithException) {
return Mono.just(new ResponseDTO<T>(
appsmithException.getHttpStatus(),
new ErrorDTO(
appsmithException.getAppErrorCode(),
appsmithException.getErrorType(),
appsmithException.getMessage(),
appsmithException.getTitle())));
}
return Mono.just(new ResponseDTO<T>(
INTERNAL_SERVER_ERROR_STATUS, new ErrorDTO(INTERNAL_SERVER_ERROR_CODE, error.getMessage())));
}
/**
* This method is meant to be used by the client application at the time of 1st page load. Client currently makes
* several API calls to fetch all the required data. This method consolidates all that data and returns them as
* response hence enabling the client to fetch the required data via a single API call only.
*
* PLEASE TAKE CARE TO USE .cache() FOR Mono THAT GETS REUSED SO THAT FIRST PAGE LOAD PERFORMANCE DOES NOT DEGRADE.
*/
@Override
public Mono<ConsolidatedAPIResponseDTO> getConsolidatedInfoForPageLoad(
String defaultPageId, String applicationId, String branchName, ApplicationMode mode) {
/* if either of pageId or applicationId are provided then application mode must also be provided */
if (mode == null && (!isBlank(defaultPageId) || !isBlank(applicationId))) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, APP_MODE));
}
/* This object will serve as a container to hold the response of this method*/
ConsolidatedAPIResponseDTO consolidatedAPIResponseDTO = new ConsolidatedAPIResponseDTO();
/* Get user profile data */
Mono<ResponseDTO<UserProfileDTO>> userProfileDTOResponseDTOMono = sessionUserService
.getCurrentUser()
.flatMap(userService::buildUserProfileDTO)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, UserProfileDTO.class));
/* Get all feature flags data */
Mono<ResponseDTO<Map>> featureFlagsForCurrentUserResponseDTOMonoCache = userDataService
.getFeatureFlagsForCurrentUser()
.map(res -> (Map) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, Map.class))
.cache();
/* Get tenant config data */
Mono<ResponseDTO<Tenant>> tenantResponseDTOMono = tenantService
.getTenantConfiguration()
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, Tenant.class));
/* Get any product alert info */
Mono<ResponseDTO<ProductAlertResponseDTO>> productAlertResponseDTOMono = productAlertService
.getSingleApplicableMessage()
.map(messages -> {
if (!messages.isEmpty()) {
return messages.get(0);
}
return new ProductAlertResponseDTO();
})
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, ProductAlertResponseDTO.class));
if (isBlank(defaultPageId) && isBlank(applicationId)) {
List<Mono<?>> listOfCommonResponseMono = List.of(
userProfileDTOResponseDTOMono,
featureFlagsForCurrentUserResponseDTOMonoCache,
tenantResponseDTOMono,
productAlertResponseDTOMono);
return Mono.zip(listOfCommonResponseMono, responseArray -> {
consolidatedAPIResponseDTO.setV1UsersMeResp((ResponseDTO<UserProfileDTO>) responseArray[0]);
consolidatedAPIResponseDTO.setV1UsersFeaturesResp((ResponseDTO<Map<String, Boolean>>) responseArray[1]);
consolidatedAPIResponseDTO.setV1TenantsCurrentResp((ResponseDTO<Tenant>) responseArray[2]);
consolidatedAPIResponseDTO.setV1ProductAlertResp(
(ResponseDTO<ProductAlertResponseDTO>) responseArray[3]);
return consolidatedAPIResponseDTO;
});
}
/* Get view mode - EDIT or PUBLISHED */
boolean isViewMode = ApplicationMode.PUBLISHED.equals(mode);
/* Fetch application id if not provided */
Mono<String> applicationIdMonoCache;
if (isBlank(applicationId)) {
applicationIdMonoCache = applicationPageService
.getPage(defaultPageId, isViewMode)
.map(PageDTO::getApplicationId)
.cache();
} else {
applicationIdMonoCache = Mono.just(applicationId).cache();
}
/* Get all pages in application */
Mono<ResponseDTO<ApplicationPagesDTO>> applicationPagesDTOResponseDTOMonoCache = applicationIdMonoCache
.flatMap(appId -> newPageService.findApplicationPages(appId, null, branchName, mode))
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, ApplicationPagesDTO.class))
.cache();
/* Get current theme */
Mono<ResponseDTO<Theme>> applicationThemeResponseDTOMono = applicationIdMonoCache
.flatMap(appId -> themeService.getApplicationTheme(appId, mode, branchName))
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, Theme.class));
/* Get all themes */
Mono<ResponseDTO<List>> ThemesListResponseDTOMono = applicationIdMonoCache
.flatMap(appId ->
themeService.getApplicationThemes(appId, branchName).collectList())
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class));
/* Get all custom JS libraries installed in the application */
Mono<ResponseDTO<List>> allJSLibsInContextDTOResponseDTOMono = applicationIdMonoCache
.flatMap(appId -> customJSLibService.getAllJSLibsInContext(
appId, CreatorContextType.APPLICATION, branchName, isViewMode))
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class));
/* Check if release_server_dsl_migrations_enabled flag is true for the user */
Mono<Boolean> migrateDslMonoCache = featureFlagsForCurrentUserResponseDTOMonoCache
.map(ResponseDTO::getData)
.map(flagsMap -> {
if (!flagsMap.containsKey(FEATURE_FLAG_RELEASE_SERVER_DSL_MIGRATIONS_ENABLED)) {
return false;
}
return (Boolean) flagsMap.get(FEATURE_FLAG_RELEASE_SERVER_DSL_MIGRATIONS_ENABLED);
})
.cache();
Mono<ResponseDTO<PageDTO>> currentPageDTOResponseDTOMono = Mono.empty();
if (!isBlank(defaultPageId)) {
/* Get current page */
currentPageDTOResponseDTOMono = migrateDslMonoCache
.flatMap(migrateDsl -> applicationPageService.getPageAndMigrateDslByBranchAndDefaultPageId(
defaultPageId, branchName, isViewMode, migrateDsl))
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, PageDTO.class));
}
/* Fetch view specific data */
if (isViewMode) {
/* Get list of all actions in view mode */
Mono<ResponseDTO<List>> listOfActionViewResponseDTOMono = applicationIdMonoCache
.flatMap(appId -> newActionService
.getActionsForViewMode(appId, branchName)
.collectList())
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class));
/* Get list of all action collections in view mode */
Mono<ResponseDTO<List>> listOfActionCollectionViewResponseDTOMono = applicationIdMonoCache
.flatMap(appId -> actionCollectionService
.getActionCollectionsForViewMode(appId, branchName)
.collectList())
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class));
/* This list contains the Mono objects corresponding to all the data points required for view mode. All
* the Mono objects in this list will be evaluated via Mono.zip operator.
*/
List<Mono<?>> listOfMonoForPublishedApp = new ArrayList<>(List.of(
userProfileDTOResponseDTOMono,
tenantResponseDTOMono,
featureFlagsForCurrentUserResponseDTOMonoCache,
applicationPagesDTOResponseDTOMonoCache,
applicationThemeResponseDTOMono,
ThemesListResponseDTOMono,
listOfActionViewResponseDTOMono,
listOfActionCollectionViewResponseDTOMono,
allJSLibsInContextDTOResponseDTOMono,
productAlertResponseDTOMono));
if (!isBlank(defaultPageId)) {
listOfMonoForPublishedApp.add(currentPageDTOResponseDTOMono);
}
return Mono.zip(listOfMonoForPublishedApp, responseArray -> {
consolidatedAPIResponseDTO.setV1UsersMeResp((ResponseDTO<UserProfileDTO>) responseArray[0]);
consolidatedAPIResponseDTO.setV1TenantsCurrentResp((ResponseDTO<Tenant>) responseArray[1]);
consolidatedAPIResponseDTO.setV1UsersFeaturesResp((ResponseDTO<Map<String, Boolean>>) responseArray[2]);
consolidatedAPIResponseDTO.setV1PagesResp((ResponseDTO<ApplicationPagesDTO>) responseArray[3]);
consolidatedAPIResponseDTO.setV1ThemesApplicationCurrentModeResp((ResponseDTO<Theme>) responseArray[4]);
consolidatedAPIResponseDTO.setV1ThemesResp((ResponseDTO<List<Theme>>) responseArray[5]);
consolidatedAPIResponseDTO.setV1ActionsViewResp((ResponseDTO<List<ActionViewDTO>>) responseArray[6]);
consolidatedAPIResponseDTO.setV1CollectionsActionsViewResp(
(ResponseDTO<List<ActionCollectionViewDTO>>) responseArray[7]);
consolidatedAPIResponseDTO.setV1LibrariesApplicationResp(
(ResponseDTO<List<CustomJSLib>>) responseArray[8]);
consolidatedAPIResponseDTO.setV1ProductAlertResp(
(ResponseDTO<ProductAlertResponseDTO>) responseArray[9]);
if (!isBlank(defaultPageId)) {
consolidatedAPIResponseDTO.setV1PublishedPageResp((ResponseDTO<PageDTO>) responseArray[10]);
}
return consolidatedAPIResponseDTO;
});
} else {
/* Get all actions in edit mode */
Mono<ResponseDTO<List>> listOfActionResponseDTOMono = applicationIdMonoCache
.flatMap(appId -> {
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add(APPLICATION_ID, appId);
return newActionService
.getUnpublishedActions(params, branchName, false)
.collectList();
})
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class));
/* Get all action collections in edit mode */
Mono<ResponseDTO<List>> listOfActionCollectionResponseDTOMono = applicationIdMonoCache.flatMap(appId -> {
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add(APPLICATION_ID, appId);
return actionCollectionService
.getPopulatedActionCollectionsByViewMode(params, false, branchName)
.collectList()
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class));
});
/* Get all pages in edit mode post apply migrate DSL changes */
Mono<ResponseDTO<List>> listOfAllPageResponseDTOMono = migrateDslMonoCache
.flatMap(migrateDsl -> applicationPagesDTOResponseDTOMonoCache
.map(ResponseDTO::getData)
.map(ApplicationPagesDTO::getPages)
.flatMapMany(Flux::fromIterable)
.flatMap(page -> applicationPageService.getPageAndMigrateDslByBranchAndDefaultPageId(
page.getDefaultPageId(), branchName, false, migrateDsl))
.collect(Collectors.toList()))
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class));
/* Get all workspace id */
Mono<String> workspaceIdMonoCache = applicationPagesDTOResponseDTOMonoCache
.map(ResponseDTO::getData)
.map(ApplicationPagesDTO::getWorkspaceId)
.cache();
/* Get all plugins in workspace */
Mono<ResponseDTO<List>> listOfPluginsResponseDTOMonoCache = workspaceIdMonoCache
.flatMap(workspaceId -> {
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add(WORKSPACE_ID, workspaceId);
return pluginService.get(params).collectList();
})
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class))
.cache();
/* Get all datasources in workspace */
Mono<ResponseDTO<List>> listOfDatasourcesResponseDTOMonoCache = workspaceIdMonoCache
.flatMap(workspaceId -> {
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add(WORKSPACE_ID, workspaceId);
return datasourceService.getAllWithStorages(params).collectList();
})
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class))
.cache();
/* Get form config for all relevant plugins by following this rule:
* (a) there is at least one datasource of the plugin type alive in the workspace
* (b) include REST API and GraphQL API plugin always
* (c) ignore any other plugin
* */
Mono<ResponseDTO<Map>> listOfFormConfigsResponseDTOMono = Mono.zip(
listOfPluginsResponseDTOMonoCache, listOfDatasourcesResponseDTOMonoCache)
.map(tuple2 -> {
Set<String> setOfAllPluginIdsToGetFormConfig = new HashSet<>();
List<Plugin> pluginList = tuple2.getT1().getData();
List<Datasource> datasourcesList = tuple2.getT2().getData();
datasourcesList.stream()
.filter(datasource -> !isBlank(datasource.getPluginId()))
.forEach(datasource -> setOfAllPluginIdsToGetFormConfig.add(datasource.getPluginId()));
pluginList.stream()
.filter(plugin -> REST_API_PLUGIN.equals(plugin.getPackageName())
|| GRAPHQL_PLUGIN.equals(plugin.getPackageName()))
.forEach(plugin -> setOfAllPluginIdsToGetFormConfig.add(plugin.getId()));
return setOfAllPluginIdsToGetFormConfig;
})
.flatMapMany(Flux::fromIterable)
.flatMap(pluginId ->
pluginService.getFormConfig(pluginId).map(formConfig -> Pair.of(pluginId, formConfig)))
.collectList()
.map(listOfFormConfig -> {
Map<String, Map> pluginIdToFormConfigMap = new HashMap<>();
listOfFormConfig.stream().forEach(individualConfigMap -> {
String pluginId = individualConfigMap.getFirst();
Map config = individualConfigMap.getSecond();
pluginIdToFormConfigMap.put(pluginId, config);
});
return pluginIdToFormConfigMap;
})
.map(res -> (Map) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, Map.class));
/* List of mock datasources available to the user */
Mono<ResponseDTO<List>> mockDataListResponseDTOMono = mockDataService
.getMockDataSet()
.map(MockDataDTO::getMockdbs)
.map(res -> (List) res)
.map(this::getSuccessResponse)
.onErrorResume(error -> getErrorResponseMono(error, List.class));
/* This list contains the Mono objects corresponding to all the data points required for edit mode. All
* the Mono objects in this list will be evaluated via Mono.zip operator
*/
List<Mono<?>> listOfMonoForEditMode = new ArrayList<>(List.of(
userProfileDTOResponseDTOMono,
tenantResponseDTOMono,
featureFlagsForCurrentUserResponseDTOMonoCache,
applicationPagesDTOResponseDTOMonoCache,
applicationThemeResponseDTOMono,
ThemesListResponseDTOMono,
allJSLibsInContextDTOResponseDTOMono,
productAlertResponseDTOMono,
listOfActionResponseDTOMono,
listOfActionCollectionResponseDTOMono,
listOfAllPageResponseDTOMono,
listOfPluginsResponseDTOMonoCache,
listOfDatasourcesResponseDTOMonoCache,
listOfFormConfigsResponseDTOMono,
mockDataListResponseDTOMono));
if (!isBlank(defaultPageId)) {
listOfMonoForEditMode.add(currentPageDTOResponseDTOMono);
}
return Mono.zip(listOfMonoForEditMode, responseArray -> {
consolidatedAPIResponseDTO.setV1UsersMeResp((ResponseDTO<UserProfileDTO>) responseArray[0]);
consolidatedAPIResponseDTO.setV1TenantsCurrentResp((ResponseDTO<Tenant>) responseArray[1]);
consolidatedAPIResponseDTO.setV1UsersFeaturesResp((ResponseDTO<Map<String, Boolean>>) responseArray[2]);
consolidatedAPIResponseDTO.setV1PagesResp((ResponseDTO<ApplicationPagesDTO>) responseArray[3]);
consolidatedAPIResponseDTO.setV1ThemesApplicationCurrentModeResp((ResponseDTO<Theme>) responseArray[4]);
consolidatedAPIResponseDTO.setV1ThemesResp((ResponseDTO<List<Theme>>) responseArray[5]);
consolidatedAPIResponseDTO.setV1LibrariesApplicationResp(
(ResponseDTO<List<CustomJSLib>>) responseArray[6]);
consolidatedAPIResponseDTO.setV1ProductAlertResp(
(ResponseDTO<ProductAlertResponseDTO>) responseArray[7]);
consolidatedAPIResponseDTO.setV1ActionsResp((ResponseDTO<List<ActionDTO>>) responseArray[8]);
consolidatedAPIResponseDTO.setV1CollectionsActionsResp(
(ResponseDTO<List<ActionCollectionDTO>>) responseArray[9]);
consolidatedAPIResponseDTO.setV1PageDSLs((ResponseDTO<List<PageDTO>>) responseArray[10]);
consolidatedAPIResponseDTO.setV1PluginsResp((ResponseDTO<List<Plugin>>) responseArray[11]);
consolidatedAPIResponseDTO.setV1DatasourcesResp((ResponseDTO<List<Datasource>>) responseArray[12]);
consolidatedAPIResponseDTO.setV1PluginFormConfigsResp(
(ResponseDTO<Map<String, Map>>) responseArray[13]);
consolidatedAPIResponseDTO.setV1DatasourcesMockResp((ResponseDTO<List<MockDataSet>>) responseArray[14]);
if (!isBlank(defaultPageId)) {
consolidatedAPIResponseDTO.setV1PageResp((ResponseDTO<PageDTO>) responseArray[15]);
}
return consolidatedAPIResponseDTO;
});
}
}
}

View File

@ -163,7 +163,7 @@ public class DatasourceContextServiceCEImpl implements DatasourceContextServiceC
public boolean shouldCacheContextForThisPlugin(Plugin plugin) {
// !(a || b) => (!a) & (!b)
return !PluginConstants.PackageName.REST_API_PLUGIN.equals(plugin.getPackageName())
&& !PluginConstants.PackageName.GRAPH_QL_PLUGIN.equals(plugin.getPackageName());
&& !PluginConstants.PackageName.GRAPHQL_PLUGIN.equals(plugin.getPackageName());
}
public Mono<Object> updateDatasourceAndSetAuthentication(Object connection, DatasourceStorage datasourceStorage) {

View File

@ -0,0 +1,614 @@
package com.appsmith.server.services;
import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.Datasource;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.datasources.base.DatasourceService;
import com.appsmith.server.domains.ApplicationMode;
import com.appsmith.server.domains.CustomJSLib;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.domains.Theme;
import com.appsmith.server.domains.User;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.server.dtos.ActionCollectionViewDTO;
import com.appsmith.server.dtos.ActionViewDTO;
import com.appsmith.server.dtos.ApplicationPagesDTO;
import com.appsmith.server.dtos.ConsolidatedAPIResponseDTO;
import com.appsmith.server.dtos.MockDataDTO;
import com.appsmith.server.dtos.MockDataSet;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.dtos.PageNameIdDTO;
import com.appsmith.server.dtos.ProductAlertResponseDTO;
import com.appsmith.server.dtos.UserProfileDTO;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.jslibs.base.CustomJSLibService;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.plugins.base.PluginService;
import com.appsmith.server.themes.base.ThemeService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
@SpringBootTest
@ExtendWith(SpringExtension.class)
public class ConsolidatedAPIServiceImplTest {
@SpyBean
ConsolidatedAPIService consolidatedAPIService;
@SpyBean
SessionUserService sessionUserService;
@SpyBean
UserService userService;
@SpyBean
UserDataService userDataService;
@SpyBean
TenantService tenantService;
@SpyBean
ProductAlertService productAlertService;
@SpyBean
NewPageService newPageService;
@SpyBean
NewActionService newActionService;
@SpyBean
ActionCollectionService actionCollectionService;
@SpyBean
ThemeService themeService;
@SpyBean
ApplicationPageService applicationPageService;
@SpyBean
CustomJSLibService customJSLibService;
@SpyBean
PluginService pluginService;
@SpyBean
ApplicationService applicationService;
@SpyBean
DatasourceService datasourceService;
@SpyBean
MockDataService mockDataService;
@Test
public void testErrorWhenModeIsNullAndPageIdAvailable() {
Mono<ConsolidatedAPIResponseDTO> consolidatedInfoForPageLoad =
consolidatedAPIService.getConsolidatedInfoForPageLoad("pageId", null, null, null);
StepVerifier.create(consolidatedInfoForPageLoad).verifyErrorSatisfies(error -> {
assertTrue(error instanceof AppsmithException);
assertEquals("Please enter a valid parameter appMode.", error.getMessage());
});
}
@Test
public void testPageLoadResponseWhenPageIdAndApplicationIdMissing() {
User sampleUser = new User();
doReturn(Mono.just(sampleUser)).when(sessionUserService).getCurrentUser();
UserProfileDTO sampleUserProfileDTO = new UserProfileDTO();
sampleUserProfileDTO.setName("sampleUserProfileDTO");
doReturn(Mono.just(sampleUserProfileDTO)).when(userService).buildUserProfileDTO(any());
Map<String, Boolean> sampleFeatureFlagMap = new HashMap<>();
sampleFeatureFlagMap.put("sampleFeatureFlag", true);
doReturn(Mono.just(sampleFeatureFlagMap)).when(userDataService).getFeatureFlagsForCurrentUser();
Tenant sampleTenant = new Tenant();
sampleTenant.setDisplayName("sampleTenant");
doReturn(Mono.just(sampleTenant)).when(tenantService).getTenantConfiguration();
ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO();
sampleProductAlertResponseDTO.setTitle("sampleProductAlert");
doReturn(Mono.just(List.of(sampleProductAlertResponseDTO)))
.when(productAlertService)
.getSingleApplicableMessage();
Mono<ConsolidatedAPIResponseDTO> consolidatedInfoForPageLoad =
consolidatedAPIService.getConsolidatedInfoForPageLoad(
"pageId", "appId", "branch", ApplicationMode.PUBLISHED);
StepVerifier.create(consolidatedInfoForPageLoad)
.assertNext(consolidatedAPIResponseDTO -> {
assertNotNull(consolidatedAPIResponseDTO.getV1UsersMeResp());
assertEquals(
"sampleUserProfileDTO",
consolidatedAPIResponseDTO
.getV1UsersMeResp()
.getData()
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1TenantsCurrentResp());
assertEquals(
"sampleTenant",
consolidatedAPIResponseDTO
.getV1TenantsCurrentResp()
.getData()
.getDisplayName());
assertNotNull(consolidatedAPIResponseDTO.getV1UsersFeaturesResp());
assertTrue(consolidatedAPIResponseDTO
.getV1UsersFeaturesResp()
.getData()
.get("sampleFeatureFlag"));
assertNotNull(consolidatedAPIResponseDTO.getV1ProductAlertResp());
assertEquals(
"sampleProductAlert",
consolidatedAPIResponseDTO
.getV1ProductAlertResp()
.getData()
.getTitle());
})
.verifyComplete();
}
@Test
public void testPageLoadResponseForViewMode() {
User sampleUser = new User();
doReturn(Mono.just(sampleUser)).when(sessionUserService).getCurrentUser();
UserProfileDTO sampleUserProfileDTO = new UserProfileDTO();
sampleUserProfileDTO.setName("sampleUserProfileDTO");
doReturn(Mono.just(sampleUserProfileDTO)).when(userService).buildUserProfileDTO(any());
Map<String, Boolean> sampleFeatureFlagMap = new HashMap<>();
sampleFeatureFlagMap.put("sampleFeatureFlag", true);
doReturn(Mono.just(sampleFeatureFlagMap)).when(userDataService).getFeatureFlagsForCurrentUser();
Tenant sampleTenant = new Tenant();
sampleTenant.setDisplayName("sampleTenant");
doReturn(Mono.just(sampleTenant)).when(tenantService).getTenantConfiguration();
ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO();
sampleProductAlertResponseDTO.setTitle("sampleProductAlert");
doReturn(Mono.just(List.of(sampleProductAlertResponseDTO)))
.when(productAlertService)
.getSingleApplicableMessage();
ApplicationPagesDTO sampleApplicationPagesDTO = new ApplicationPagesDTO();
sampleApplicationPagesDTO.setWorkspaceId("sampleWorkspaceId");
doReturn(Mono.just(sampleApplicationPagesDTO))
.when(newPageService)
.findApplicationPages(anyString(), any(), anyString(), any());
Theme sampleTheme = new Theme();
sampleTheme.setName("sampleTheme");
doReturn(Mono.just(sampleTheme)).when(themeService).getApplicationTheme(anyString(), any(), anyString());
doReturn(Flux.just(sampleTheme)).when(themeService).getApplicationThemes(anyString(), anyString());
CustomJSLib sampleCustomJSLib = new CustomJSLib();
sampleCustomJSLib.setName("sampleJSLib");
doReturn(Mono.just(List.of(sampleCustomJSLib)))
.when(customJSLibService)
.getAllJSLibsInContext(anyString(), any(), anyString(), anyBoolean());
PageDTO samplePageDTO = new PageDTO();
samplePageDTO.setName("samplePageDTO");
doReturn(Mono.just(samplePageDTO))
.when(applicationPageService)
.getPageAndMigrateDslByBranchAndDefaultPageId(anyString(), anyString(), anyBoolean(), anyBoolean());
ActionViewDTO sampleActionViewDTO = new ActionViewDTO();
sampleActionViewDTO.setName("sampleActionViewDTO");
doReturn(Flux.just(sampleActionViewDTO)).when(newActionService).getActionsForViewMode(anyString(), anyString());
ActionCollectionViewDTO sampleActionCollectionViewDTO = new ActionCollectionViewDTO();
sampleActionCollectionViewDTO.setName("sampleActionCollectionViewDTO");
doReturn(Flux.just(sampleActionCollectionViewDTO))
.when(actionCollectionService)
.getActionCollectionsForViewMode(anyString(), anyString());
Mono<ConsolidatedAPIResponseDTO> consolidatedInfoForPageLoad =
consolidatedAPIService.getConsolidatedInfoForPageLoad(
"pageId", "appId", "branch", ApplicationMode.PUBLISHED);
StepVerifier.create(consolidatedInfoForPageLoad)
.assertNext(consolidatedAPIResponseDTO -> {
assertNotNull(consolidatedAPIResponseDTO.getV1ActionsViewResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1ActionsViewResp()
.getData()
.size());
assertEquals(
"sampleActionViewDTO",
consolidatedAPIResponseDTO
.getV1ActionsViewResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1UsersMeResp());
assertEquals(
"sampleUserProfileDTO",
consolidatedAPIResponseDTO
.getV1UsersMeResp()
.getData()
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1TenantsCurrentResp());
assertEquals(
"sampleTenant",
consolidatedAPIResponseDTO
.getV1TenantsCurrentResp()
.getData()
.getDisplayName());
assertNotNull(consolidatedAPIResponseDTO.getV1UsersFeaturesResp());
assertTrue(consolidatedAPIResponseDTO
.getV1UsersFeaturesResp()
.getData()
.get("sampleFeatureFlag"));
assertNotNull(consolidatedAPIResponseDTO.getV1PagesResp());
assertEquals(
"sampleWorkspaceId",
consolidatedAPIResponseDTO
.getV1PagesResp()
.getData()
.getWorkspaceId());
assertNotNull(consolidatedAPIResponseDTO.getV1ThemesApplicationCurrentModeResp());
assertEquals(
"sampleTheme",
consolidatedAPIResponseDTO
.getV1ThemesApplicationCurrentModeResp()
.getData()
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1ThemesResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1ThemesResp()
.getData()
.size());
assertEquals(
"sampleTheme",
consolidatedAPIResponseDTO
.getV1ThemesResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1CollectionsActionsViewResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1CollectionsActionsViewResp()
.getData()
.size());
assertEquals(
"sampleActionCollectionViewDTO",
consolidatedAPIResponseDTO
.getV1CollectionsActionsViewResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1PublishedPageResp());
assertEquals(
"samplePageDTO",
consolidatedAPIResponseDTO
.getV1PublishedPageResp()
.getData()
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1LibrariesApplicationResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1LibrariesApplicationResp()
.getData()
.size());
assertEquals(
"sampleJSLib",
consolidatedAPIResponseDTO
.getV1LibrariesApplicationResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1ProductAlertResp());
assertEquals(
"sampleProductAlert",
consolidatedAPIResponseDTO
.getV1ProductAlertResp()
.getData()
.getTitle());
})
.verifyComplete();
}
@Test
public void testPageLoadResponseForEditMode() {
User sampleUser = new User();
doReturn(Mono.just(sampleUser)).when(sessionUserService).getCurrentUser();
UserProfileDTO sampleUserProfileDTO = new UserProfileDTO();
sampleUserProfileDTO.setName("sampleUserProfileDTO");
doReturn(Mono.just(sampleUserProfileDTO)).when(userService).buildUserProfileDTO(any());
Map<String, Boolean> sampleFeatureFlagMap = new HashMap<>();
sampleFeatureFlagMap.put("sampleFeatureFlag", true);
doReturn(Mono.just(sampleFeatureFlagMap)).when(userDataService).getFeatureFlagsForCurrentUser();
Tenant sampleTenant = new Tenant();
sampleTenant.setDisplayName("sampleTenant");
doReturn(Mono.just(sampleTenant)).when(tenantService).getTenantConfiguration();
ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO();
sampleProductAlertResponseDTO.setTitle("sampleProductAlert");
doReturn(Mono.just(List.of(sampleProductAlertResponseDTO)))
.when(productAlertService)
.getSingleApplicableMessage();
ApplicationPagesDTO sampleApplicationPagesDTO = new ApplicationPagesDTO();
sampleApplicationPagesDTO.setWorkspaceId("sampleWorkspaceId");
doReturn(Mono.just(sampleApplicationPagesDTO))
.when(newPageService)
.findApplicationPages(anyString(), any(), anyString(), any());
Theme sampleTheme = new Theme();
sampleTheme.setName("sampleTheme");
doReturn(Mono.just(sampleTheme)).when(themeService).getApplicationTheme(anyString(), any(), anyString());
doReturn(Flux.just(sampleTheme)).when(themeService).getApplicationThemes(anyString(), anyString());
CustomJSLib sampleCustomJSLib = new CustomJSLib();
sampleCustomJSLib.setName("sampleJSLib");
doReturn(Mono.just(List.of(sampleCustomJSLib)))
.when(customJSLibService)
.getAllJSLibsInContext(anyString(), any(), anyString(), anyBoolean());
PageDTO samplePageDTO = new PageDTO();
samplePageDTO.setName("samplePageDTO");
doReturn(Mono.just(samplePageDTO))
.when(applicationPageService)
.getPageAndMigrateDslByBranchAndDefaultPageId(anyString(), anyString(), anyBoolean(), anyBoolean());
doReturn(Mono.just(samplePageDTO))
.when(applicationPageService)
.getPageAndMigrateDslByBranchAndDefaultPageId(anyString(), anyString(), anyBoolean(), anyBoolean());
ActionDTO sampleActionDTO = new ActionDTO();
sampleActionDTO.setName("sampleActionDTO");
doReturn(Flux.just(sampleActionDTO))
.when(newActionService)
.getUnpublishedActions(any(), anyString(), anyBoolean());
ActionCollectionDTO sampleActionCollectionDTO = new ActionCollectionDTO();
sampleActionCollectionDTO.setName("sampleActionCollectionDTO");
doReturn(Flux.just(sampleActionCollectionDTO))
.when(actionCollectionService)
.getPopulatedActionCollectionsByViewMode(any(), anyBoolean(), anyString());
PageNameIdDTO samplePageNameIdDTO = new PageNameIdDTO();
samplePageNameIdDTO.setName("samplePageNameIdDTO");
samplePageNameIdDTO.setDefaultPageId("pageId");
sampleApplicationPagesDTO.setPages(List.of(samplePageNameIdDTO));
Plugin samplePlugin = new Plugin();
samplePlugin.setName("samplePlugin");
doReturn(Flux.just(samplePlugin)).when(pluginService).get(any());
Datasource sampleDatasource = new Datasource();
sampleDatasource.setName("sampleDatasource");
sampleDatasource.setPluginId("samplePluginId");
doReturn(Flux.just(sampleDatasource)).when(datasourceService).getAllWithStorages(any());
Map<String, Map> sampleFormConfig = new HashMap<>();
sampleFormConfig.put("key", Map.of());
doReturn(Mono.just(sampleFormConfig)).when(pluginService).getFormConfig(anyString());
MockDataSet sampleMockDataSet = new MockDataSet();
sampleMockDataSet.setName("sampleMockDataSet");
MockDataDTO sampleMockDataDTO = new MockDataDTO();
sampleMockDataDTO.setMockdbs(List.of(sampleMockDataSet));
doReturn(Mono.just(sampleMockDataDTO)).when(mockDataService).getMockDataSet();
Mono<ConsolidatedAPIResponseDTO> consolidatedInfoForPageLoad =
consolidatedAPIService.getConsolidatedInfoForPageLoad(
"pageId", "appId", "branch", ApplicationMode.EDIT);
StepVerifier.create(consolidatedInfoForPageLoad)
.assertNext(consolidatedAPIResponseDTO -> {
assertNotNull(consolidatedAPIResponseDTO.getV1UsersMeResp());
assertEquals(
"sampleUserProfileDTO",
consolidatedAPIResponseDTO
.getV1UsersMeResp()
.getData()
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1TenantsCurrentResp());
assertEquals(
"sampleTenant",
consolidatedAPIResponseDTO
.getV1TenantsCurrentResp()
.getData()
.getDisplayName());
assertNotNull(consolidatedAPIResponseDTO.getV1UsersFeaturesResp());
assertTrue(consolidatedAPIResponseDTO
.getV1UsersFeaturesResp()
.getData()
.get("sampleFeatureFlag"));
assertNotNull(consolidatedAPIResponseDTO.getV1PagesResp());
assertEquals(
"sampleWorkspaceId",
consolidatedAPIResponseDTO
.getV1PagesResp()
.getData()
.getWorkspaceId());
assertNotNull(consolidatedAPIResponseDTO.getV1ThemesApplicationCurrentModeResp());
assertEquals(
"sampleTheme",
consolidatedAPIResponseDTO
.getV1ThemesApplicationCurrentModeResp()
.getData()
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1ThemesResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1ThemesResp()
.getData()
.size());
assertEquals(
"sampleTheme",
consolidatedAPIResponseDTO
.getV1ThemesResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1PagesResp());
assertEquals(
"sampleWorkspaceId",
consolidatedAPIResponseDTO
.getV1PagesResp()
.getData()
.getWorkspaceId());
assertNotNull(consolidatedAPIResponseDTO.getV1LibrariesApplicationResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1LibrariesApplicationResp()
.getData()
.size());
assertEquals(
"sampleJSLib",
consolidatedAPIResponseDTO
.getV1LibrariesApplicationResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1ProductAlertResp());
assertEquals(
"sampleProductAlert",
consolidatedAPIResponseDTO
.getV1ProductAlertResp()
.getData()
.getTitle());
assertNotNull(consolidatedAPIResponseDTO.getV1ActionsResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1ActionsResp()
.getData()
.size());
assertEquals(
"sampleActionDTO",
consolidatedAPIResponseDTO
.getV1ActionsResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1CollectionsActionsResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1CollectionsActionsResp()
.getData()
.size());
assertEquals(
"sampleActionCollectionDTO",
consolidatedAPIResponseDTO
.getV1CollectionsActionsResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1PageDSLs());
assertEquals(
1,
consolidatedAPIResponseDTO.getV1PageDSLs().getData().size());
assertEquals(
"samplePageDTO",
consolidatedAPIResponseDTO
.getV1PageDSLs()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1PluginsResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1PluginsResp()
.getData()
.size());
assertEquals(
"samplePlugin",
consolidatedAPIResponseDTO
.getV1PluginsResp()
.getData()
.get(0)
.getName());
assertNotNull(consolidatedAPIResponseDTO.getV1PluginFormConfigsResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1PluginFormConfigsResp()
.getData()
.keySet()
.size());
assertTrue(consolidatedAPIResponseDTO
.getV1PluginFormConfigsResp()
.getData()
.containsKey("samplePluginId"));
assertNotNull(consolidatedAPIResponseDTO.getV1DatasourcesMockResp());
assertEquals(
1,
consolidatedAPIResponseDTO
.getV1DatasourcesMockResp()
.getData()
.size());
assertEquals(
"sampleMockDataSet",
consolidatedAPIResponseDTO
.getV1DatasourcesMockResp()
.getData()
.get(0)
.getName());
})
.verifyComplete();
}
}