diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java index 1f046c8ba290..ec39de3168a2 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java @@ -8,6 +8,7 @@ import com.appsmith.server.datasources.base.DatasourceService; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.ApplicationMode; +import com.appsmith.server.domains.GitArtifactMetadata; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Plugin; import com.appsmith.server.dtos.ApplicationPagesDTO; @@ -42,6 +43,7 @@ import reactor.core.observability.micrometer.Micrometer; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; import java.util.ArrayList; import java.util.HashMap; @@ -204,7 +206,7 @@ public Mono getConsolidatedInfoForPageLoad( if (isBlank(basePageId)) { return Mono.when(fetches).thenReturn(consolidatedAPIResponseDTO); } - Mono branchedApplicationMonoCached; + Mono baseApplicationIdMono = Mono.just(""); if (isViewMode) { // Attempt to retrieve the application ID associated with the given base page ID from the cache. @@ -213,40 +215,118 @@ public Mono getConsolidatedInfoForPageLoad( .switchIfEmpty(Mono.just("")) .cast(String.class); } + baseApplicationIdMono = baseApplicationIdMono .name(getQualifiedSpanName(APPLICATION_ID_FETCH_REDIS_SPAN, mode)) .tap(Micrometer.observation(observationRegistry)) .cache(); - Mono branchedPageMonoCached = newPageService - .findByBranchNameAndBasePageIdAndApplicationMode(branchName, basePageId, mode) - .cache(); + Mono> applicationAndPageTupleMono = baseApplicationIdMono + .flatMap(cachedBaseApplicationId -> { + Mono applicationMono; + Mono branchedPageMonoCached; + + branchedPageMonoCached = newPageService + .findByBranchNameAndBasePageIdAndApplicationMode(branchName, basePageId, mode) + .cache(); + + if (StringUtils.hasText(cachedBaseApplicationId)) { + // Handle non-empty baseApplicationId + applicationMono = applicationService.findByBaseIdBranchNameAndApplicationMode( + cachedBaseApplicationId, branchName, mode); + } else { + // Handle empty or null baseApplicationId + applicationMono = branchedPageMonoCached.flatMap(branchedPage -> + // Use the application ID to find the complete application details. + applicationService + .findByBranchedApplicationIdAndApplicationMode( + branchedPage.getApplicationId(), mode) + .flatMap(application -> { + if (isViewMode) { + // Update the cache with the new application’s base ID for future + // queries. + return cacheableRepositoryHelper + .fetchBaseApplicationId(basePageId, application.getBaseId()) + .thenReturn(application) + .name(getQualifiedSpanName( + APPLICATION_ID_UPDATE_REDIS_SPAN, mode)) + .tap(Micrometer.observation(observationRegistry)); + } + return Mono.just(application); + })); + } - branchedApplicationMonoCached = baseApplicationIdMono.flatMap(cachedBaseApplicationId -> { - if (!StringUtils.hasText(cachedBaseApplicationId)) { - // Handle empty or null baseApplicationId - return branchedPageMonoCached.flatMap(branchedPage -> - // Use the application ID to find the complete application details. - applicationService - .findByBranchedApplicationIdAndApplicationMode(branchedPage.getApplicationId(), mode) - .flatMap(application -> { - if (isViewMode) { - // Update the cache with the new application’s base ID for future - // queries. - return cacheableRepositoryHelper - .fetchBaseApplicationId(basePageId, application.getBaseId()) - .thenReturn(application) - .name(getQualifiedSpanName(APPLICATION_ID_UPDATE_REDIS_SPAN, mode)) - .tap(Micrometer.observation(observationRegistry)); + if (StringUtils.hasText(branchName)) { + + // If in case the application is a non git connected application and the branch name url param + // is present, then we must default to the app without any branches. + return applicationMono.zipWith(branchedPageMonoCached).onErrorResume(error -> { + // This situation would arise if page or application is not returned. + // here we would land on error instead of empty because both apis which are being + // called errors out on empty returns. + + log.info( + "application or page has for base pageId {} and branchName {} has not been found.", + basePageId, + branchName); + if (error instanceof AppsmithException) { + Mono basePageMono = + newPageService.findByBranchNameAndBasePageIdAndApplicationMode( + null, basePageId, mode); + + return basePageMono.flatMap(basePage -> { + if (StringUtils.hasText(basePage.getBranchName())) { + // If the branch name is present then the application is git connected + // the error should be thrown. + // TODO: verify if branch name could be residue from old git connection + // Application metadata is absolute check for the same. + return Mono.error(error); } - return Mono.just(application); - })); - } else { - // Handle non-empty baseApplicationId - return applicationService.findByBaseIdBranchNameAndApplicationMode( - cachedBaseApplicationId, branchName, mode); - } - }); + + return applicationService + .findByBranchedApplicationIdAndApplicationMode( + basePage.getApplicationId(), mode) + .zipWith(basePageMono) + .map(tuple2 -> { + log.info( + "The branchName url param should not be associated with application {} as this is not a git connected application", + tuple2.getT1().getId()); + return tuple2; + }); + }); + } + + return Mono.error(error); + }); + } + + return applicationMono.flatMap(application -> { + GitArtifactMetadata gitMetadata = application.getGitArtifactMetadata(); + + if (gitMetadata == null + || gitMetadata.getDefaultBranchName().equals(gitMetadata.getBranchName())) { + return Mono.just(application).zipWith(branchedPageMonoCached); + } + + // The git connected application has not been queried with branch param, + // and the base branch is not same as the default branch. + // we need to find return the default branch from here. + + String defaultBranchName = gitMetadata.getDefaultBranchName(); + + return applicationService + .findByBaseIdBranchNameAndApplicationMode(application.getId(), defaultBranchName, mode) + .zipWith(newPageService.findByBranchNameAndBasePageIdAndApplicationMode( + defaultBranchName, basePageId, mode)); + }); + }) + .cache(); + + Mono branchedPageMonoCached = + applicationAndPageTupleMono.map(Tuple2::getT2).cache(); + + Mono branchedApplicationMonoCached = + applicationAndPageTupleMono.map(Tuple2::getT1).cache(); branchedApplicationMonoCached = branchedApplicationMonoCached .name(getQualifiedSpanName(APPLICATION_ID_SPAN, mode)) @@ -307,8 +387,9 @@ public Mono getConsolidatedInfoForPageLoad( if (!isBlank(basePageId)) { /* Get current page */ - fetches.add(applicationPageService - .getPageAndMigrateDslByBranchAndBasePageId(basePageId, branchName, isViewMode, true) + fetches.add(branchedPageMonoCached + .flatMap(branchedPage -> applicationPageService.getPageAndMigrateDslByBranchedPageId( + branchedPage.getId(), isViewMode, true)) .as(this::toResponseDTO) .doOnError(e -> log.error("Error fetching current page", e)) .doOnSuccess(consolidatedAPIResponseDTO::setPageWithMigratedDsl) @@ -320,11 +401,9 @@ public Mono getConsolidatedInfoForPageLoad( if (isViewMode) { /* Get list of all actions of the page in view mode */ if (!isBlank(basePageId)) { - // When branchName is null, we don't need to fetch page from DB to derive pageId - // We can simply reuse the pageId that is passed by client to query actions - Mono branchedPageIdMono = !StringUtils.hasText(branchName) - ? Mono.just(basePageId) - : branchedPageMonoCached.map(NewPage::getId); + // For a git connected application the desired branch name may differ from the base if no + // branch name is provided hence, we would still need to check this. + Mono branchedPageIdMono = branchedPageMonoCached.map(NewPage::getId); fetches.add(branchedPageIdMono .flatMap(branchedPageId -> newActionService .getActionsForViewModeByPageId(branchedPageId) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceImplTest.java index 97e651a6b2ea..288cef9864cb 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceImplTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceImplTest.java @@ -8,12 +8,15 @@ import com.appsmith.server.datasources.base.DatasourceService; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.ApplicationMode; +import com.appsmith.server.domains.ApplicationPage; import com.appsmith.server.domains.CustomJSLib; +import com.appsmith.server.domains.GitArtifactMetadata; import com.appsmith.server.domains.NewPage; 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.domains.UserData; import com.appsmith.server.dtos.ActionCollectionDTO; import com.appsmith.server.dtos.ActionCollectionViewDTO; import com.appsmith.server.dtos.ActionViewDTO; @@ -66,6 +69,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; @@ -231,6 +235,7 @@ public void testPageLoadResponseForViewMode() { NewPage mockNewPage = new NewPage(); mockNewPage.setApplicationId("mockApplicationId"); mockNewPage.setId("mockPageId"); + mockNewPage.setBranchName("branch"); doReturn(Mono.just(mockNewPage)) .when(spyNewPageService) .findByBranchNameAndBasePageId(anyString(), anyString(), any(), any()); @@ -239,10 +244,6 @@ public void testPageLoadResponseForViewMode() { .when(spyApplicationPageService) .getPagesBasedOnApplicationMode(any(), any()); - doReturn(Mono.just(new PageDTO())) - .when(spyApplicationPageService) - .getPageAndMigrateDslByBranchAndBasePageId(anyString(), anyString(), anyBoolean(), anyBoolean()); - doReturn(Mono.just(sampleApplicationPagesDTO)) .when(spyNewPageService) .createApplicationPagesDTO(any(), any(), anyBoolean(), anyBoolean()); @@ -262,7 +263,7 @@ public void testPageLoadResponseForViewMode() { samplePageDTO.setName("samplePageDTO"); doReturn(Mono.just(samplePageDTO)) .when(spyApplicationPageService) - .getPageAndMigrateDslByBranchAndBasePageId(anyString(), anyString(), anyBoolean(), anyBoolean()); + .getPageAndMigrateDslByBranchedPageId(anyString(), anyBoolean(), anyBoolean()); ActionViewDTO sampleActionViewDTO = new ActionViewDTO(); sampleActionViewDTO.setName("sampleActionViewDTO"); @@ -432,7 +433,7 @@ public void testPageLoadResponseForEditMode() { doReturn(Mono.just(new PageDTO())) .when(spyApplicationPageService) - .getPageAndMigrateDslByBranchAndBasePageId(anyString(), anyString(), anyBoolean(), anyBoolean()); + .getPageAndMigrateDslByBranchedPageId(anyString(), anyBoolean(), anyBoolean()); doReturn(Mono.just(sampleApplicationPagesDTO)) .when(spyNewPageService) @@ -454,7 +455,7 @@ public void testPageLoadResponseForEditMode() { doReturn(Mono.just(samplePageDTO)) .doReturn(Mono.just(samplePageDTO)) .when(spyApplicationPageService) - .getPageAndMigrateDslByBranchAndBasePageId(anyString(), anyString(), anyBoolean(), anyBoolean()); + .getPageAndMigrateDslByBranchedPageId(anyString(), anyBoolean(), anyBoolean()); doReturn(Mono.just(samplePageDTO)) .doReturn(Mono.just(samplePageDTO)) @@ -877,4 +878,539 @@ public void testErrorResponseWhenAnonymousUserAccessPrivateApp() { }) .verifyComplete(); } + + @Test + public void testPageLoadResponseForViewMode_whenBranchNameIsPresentInNonGitApp() { + User sampleUser = new User(); + when(mockSessionUserService.getCurrentUser()).thenReturn(Mono.just(sampleUser)); + + UserProfileDTO sampleUserProfileDTO = new UserProfileDTO(); + sampleUserProfileDTO.setName("sampleUserProfileDTO"); + when(mockUserService.buildUserProfileDTO(any())).thenReturn(Mono.just(sampleUserProfileDTO)); + + Map sampleFeatureFlagMap = new HashMap<>(); + sampleFeatureFlagMap.put("sampleFeatureFlag", true); + when(mockUserDataService.getFeatureFlagsForCurrentUser()).thenReturn(Mono.just(sampleFeatureFlagMap)); + + Tenant sampleTenant = new Tenant(); + sampleTenant.setDisplayName("sampleTenant"); + when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + + ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); + sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); + when(mockProductAlertService.getSingleApplicableMessage()) + .thenReturn(Mono.just(List.of(sampleProductAlertResponseDTO))); + + ApplicationPagesDTO sampleApplicationPagesDTO = new ApplicationPagesDTO(); + sampleApplicationPagesDTO.setWorkspaceId("sampleWorkspaceId"); + + Application mockApplication = new Application(); + mockApplication.setId("mockApplicationId"); + doReturn(Mono.just(mockApplication)) + .when(spyApplicationService) + .findByBranchedApplicationIdAndApplicationMode(anyString(), any()); + + NewPage mockNewPage = new NewPage(); + mockNewPage.setApplicationId("mockApplicationId"); + mockNewPage.setId("mockPageId"); + + doReturn(Mono.just(mockNewPage)) + .when(spyNewPageService) + .findByBranchNameAndBasePageId(eq(null), eq("mockPageId"), any(), any()); + + doReturn(Mono.just(List.of(mockNewPage))) + .when(spyApplicationPageService) + .getPagesBasedOnApplicationMode(any(), any()); + + doReturn(Mono.just(sampleApplicationPagesDTO)) + .when(spyNewPageService) + .createApplicationPagesDTO(any(), any(), anyBoolean(), anyBoolean()); + + Theme sampleTheme = new Theme(); + sampleTheme.setName("sampleTheme"); + doReturn(Mono.just(sampleTheme)).when(spyThemeService).getApplicationTheme(anyString(), any()); + doReturn(Flux.just(sampleTheme)).when(spyThemeService).getApplicationThemes(anyString()); + + CustomJSLib sampleCustomJSLib = new CustomJSLib(); + sampleCustomJSLib.setName("sampleJSLib"); + doReturn(Mono.just(List.of(sampleCustomJSLib))) + .when(spyCustomJSLibService) + .getAllJSLibsInContext(anyString(), any(), anyBoolean()); + + PageDTO samplePageDTO = new PageDTO(); + samplePageDTO.setName("samplePageDTO"); + doReturn(Mono.just(samplePageDTO)) + .when(spyApplicationPageService) + .getPageAndMigrateDslByBranchedPageId(anyString(), anyBoolean(), anyBoolean()); + + ActionViewDTO sampleActionViewDTO = new ActionViewDTO(); + sampleActionViewDTO.setName("sampleActionViewDTO"); + doReturn(Flux.just(sampleActionViewDTO)).when(spyNewActionService).getActionsForViewModeByPageId(anyString()); + + ActionCollectionViewDTO sampleActionCollectionViewDTO = new ActionCollectionViewDTO(); + sampleActionCollectionViewDTO.setName("sampleActionCollectionViewDTO"); + doReturn(Flux.just(sampleActionCollectionViewDTO)) + .when(spyActionCollectionService) + .getActionCollectionsForViewMode(anyString()); + + Mono consolidatedInfoForPageLoad = + consolidatedAPIService.getConsolidatedInfoForPageLoad( + "mockPageId", null, "branch", ApplicationMode.PUBLISHED); + StepVerifier.create(consolidatedInfoForPageLoad) + .assertNext(consolidatedAPIResponseDTO -> { + assertNotNull(consolidatedAPIResponseDTO.getPublishedActions()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getPublishedActions() + .getData() + .size()); + assertEquals( + "sampleActionViewDTO", + consolidatedAPIResponseDTO + .getPublishedActions() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getUserProfile()); + assertEquals( + "sampleUserProfileDTO", + consolidatedAPIResponseDTO + .getUserProfile() + .getData() + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getTenantConfig()); + assertEquals( + "sampleTenant", + consolidatedAPIResponseDTO + .getTenantConfig() + .getData() + .getDisplayName()); + + assertNotNull(consolidatedAPIResponseDTO.getFeatureFlags()); + assertTrue(consolidatedAPIResponseDTO + .getFeatureFlags() + .getData() + .get("sampleFeatureFlag")); + + assertNotNull(consolidatedAPIResponseDTO.getPages()); + assertEquals( + "sampleWorkspaceId", + consolidatedAPIResponseDTO.getPages().getData().getWorkspaceId()); + + assertNotNull(consolidatedAPIResponseDTO.getCurrentTheme()); + assertEquals( + "sampleTheme", + consolidatedAPIResponseDTO + .getCurrentTheme() + .getData() + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getThemes()); + assertEquals( + 1, consolidatedAPIResponseDTO.getThemes().getData().size()); + assertEquals( + "sampleTheme", + consolidatedAPIResponseDTO + .getThemes() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getPublishedActionCollections()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getPublishedActionCollections() + .getData() + .size()); + assertEquals( + "sampleActionCollectionViewDTO", + consolidatedAPIResponseDTO + .getPublishedActionCollections() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getPageWithMigratedDsl()); + assertEquals( + "samplePageDTO", + consolidatedAPIResponseDTO + .getPageWithMigratedDsl() + .getData() + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getCustomJSLibraries()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getCustomJSLibraries() + .getData() + .size()); + assertEquals( + "sampleJSLib", + consolidatedAPIResponseDTO + .getCustomJSLibraries() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getProductAlert()); + assertEquals( + "sampleProductAlert", + consolidatedAPIResponseDTO + .getProductAlert() + .getData() + .getTitle()); + }) + .verifyComplete(); + } + + @Test + public void testPageLoadResponseForEditModeWhenDefaultBranchIsDifferentFromDefault() { + User sampleUser = new User(); + when(mockSessionUserService.getCurrentUser()).thenReturn(Mono.just(sampleUser)); + + UserProfileDTO sampleUserProfileDTO = new UserProfileDTO(); + sampleUserProfileDTO.setName("sampleUserProfileDTO"); + when(mockUserService.buildUserProfileDTO(any())).thenReturn(Mono.just(sampleUserProfileDTO)); + + Map sampleFeatureFlagMap = new HashMap<>(); + sampleFeatureFlagMap.put("sampleFeatureFlag", true); + when(mockUserDataService.getFeatureFlagsForCurrentUser()).thenReturn(Mono.just(sampleFeatureFlagMap)); + + when(mockUserDataService.updateLastUsedResourceAndWorkspaceList(any(), any(), any())) + .thenReturn(Mono.just(new UserData())); + + Tenant sampleTenant = new Tenant(); + sampleTenant.setDisplayName("sampleTenant"); + when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + + ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); + sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); + when(mockProductAlertService.getSingleApplicableMessage()) + .thenReturn(Mono.just(List.of(sampleProductAlertResponseDTO))); + + ApplicationPagesDTO sampleApplicationPagesDTO = new ApplicationPagesDTO(); + sampleApplicationPagesDTO.setWorkspaceId("sampleWorkspaceId"); + + Application mockApplicationBaseBranch = new Application(); + GitArtifactMetadata baseMetadata = new GitArtifactMetadata(); + baseMetadata.setBranchName("master"); + baseMetadata.setDefaultBranchName("newDefaultBranch"); + baseMetadata.setDefaultApplicationId("mockBaseId"); + mockApplicationBaseBranch.setGitArtifactMetadata(baseMetadata); + mockApplicationBaseBranch.setId("mockId"); + + doReturn(Mono.just(mockApplicationBaseBranch)) + .when(spyApplicationService) + .findByBranchedApplicationIdAndApplicationMode(anyString(), any()); + + ApplicationPage defaultApplicationPage = new ApplicationPage(); + defaultApplicationPage.setIsDefault(true); + defaultApplicationPage.setId("defaultPageId"); + + Application mockDefaultApplication = new Application(); + GitArtifactMetadata defaultMetadata = new GitArtifactMetadata(); + defaultMetadata.setBranchName("newDefaultBranch"); + defaultMetadata.setDefaultApplicationId("mockBaseId"); + mockDefaultApplication.setGitArtifactMetadata(defaultMetadata); + mockDefaultApplication.setId("defaultApplicationId"); + mockDefaultApplication.setPages(List.of(defaultApplicationPage)); + mockDefaultApplication.setWorkspaceId("sampleWorkspaceId"); + + doReturn(Mono.just(mockDefaultApplication)) + .when(spyApplicationService) + .findByBaseIdBranchNameAndApplicationMode(anyString(), anyString(), any()); + + NewPage basePage = new NewPage(); + basePage.setApplicationId("mockBaseId"); + + PageDTO unpublishedPage = new PageDTO(); + NewPage defaultAppDefaultPage = new NewPage(); + defaultAppDefaultPage.setId("defaultPageId"); + defaultAppDefaultPage.setApplicationId("defaultApplicationId"); + defaultAppDefaultPage.setUnpublishedPage(unpublishedPage); + + doReturn(Mono.just(basePage)) + .when(spyNewPageService) + .findByBranchNameAndBasePageId(eq(null), anyString(), any(), any()); + + doReturn(Mono.just(defaultAppDefaultPage)) + .when(spyNewPageService) + .findByBranchNameAndBasePageId(anyString(), anyString(), any(), any()); + + doReturn(Mono.just(List.of(defaultAppDefaultPage))) + .when(spyApplicationPageService) + .getPagesBasedOnApplicationMode(any(), any()); + + doReturn(Mono.just(new PageDTO())) + .when(spyApplicationPageService) + .getPageAndMigrateDslByBranchedPageId(anyString(), anyBoolean(), anyBoolean()); + + Theme sampleTheme = new Theme(); + sampleTheme.setName("sampleTheme"); + doReturn(Mono.just(sampleTheme)).when(spyThemeService).getApplicationTheme(anyString(), any()); + doReturn(Flux.just(sampleTheme)).when(spyThemeService).getApplicationThemes(anyString()); + + CustomJSLib sampleCustomJSLib = new CustomJSLib(); + sampleCustomJSLib.setName("sampleJSLib"); + doReturn(Mono.just(List.of(sampleCustomJSLib))) + .when(spyCustomJSLibService) + .getAllJSLibsInContext(anyString(), any(), anyBoolean()); + + PageDTO samplePageDTO = new PageDTO(); + samplePageDTO.setName("samplePageDTO"); + doReturn(Mono.just(samplePageDTO)) + .doReturn(Mono.just(samplePageDTO)) + .when(spyApplicationPageService) + .getPageAndMigrateDslByBranchedPageId(anyString(), anyBoolean(), anyBoolean()); + + doReturn(Mono.just(samplePageDTO)) + .doReturn(Mono.just(samplePageDTO)) + .when(spyApplicationPageService) + .getPageDTOAfterMigratingDSL(any(), anyBoolean(), anyBoolean()); + + doReturn(Mono.just(samplePageDTO)) + .doReturn(Mono.just(samplePageDTO)) + .when(spyApplicationPageService) + .getPageDTOAfterMigratingDSL(any(), anyBoolean(), anyBoolean()); + + ActionDTO sampleActionDTO = new ActionDTO(); + sampleActionDTO.setName("sampleActionDTO"); + sampleActionDTO.setUpdatedAt(Instant.now()); + doReturn(Flux.just(sampleActionDTO)).when(spyNewActionService).getUnpublishedActions(any(), anyBoolean()); + + ActionCollectionDTO sampleActionCollectionDTO = new ActionCollectionDTO(); + sampleActionCollectionDTO.setName("sampleActionCollectionDTO"); + doReturn(Flux.just(sampleActionCollectionDTO)) + .when(spyActionCollectionService) + .getPopulatedActionCollectionsByViewMode(any(), anyBoolean()); + + PageNameIdDTO samplePageNameIdDTO = new PageNameIdDTO(); + samplePageNameIdDTO.setName("samplePageNameIdDTO"); + sampleApplicationPagesDTO.setPages(List.of(samplePageNameIdDTO)); + + Plugin samplePlugin = new Plugin(); + samplePlugin.setName("samplePlugin"); + samplePlugin.setId("samplePluginId"); + samplePlugin.setPackageName("sample-plugin"); + Plugin sampleRestApiPlugin = new Plugin(); + sampleRestApiPlugin.setName("sampleRestApiPlugin"); + sampleRestApiPlugin.setId("sampleRestApiPluginId"); + sampleRestApiPlugin.setPackageName(REST_API_PLUGIN); + Plugin sampleGraphqlPlugin = new Plugin(); + sampleGraphqlPlugin.setName("sampleGraphqlPlugin"); + sampleGraphqlPlugin.setId("sampleGraphqlPluginId"); + sampleGraphqlPlugin.setPackageName(GRAPHQL_PLUGIN); + Plugin sampleAiPlugin = new Plugin(); + sampleAiPlugin.setName("sampleAiPlugin"); + sampleAiPlugin.setId("sampleAiPluginId"); + sampleAiPlugin.setPackageName(APPSMITH_AI_PLUGIN); + when(mockPluginService.getInWorkspace(anyString())) + .thenReturn(Flux.just(samplePlugin, sampleRestApiPlugin, sampleGraphqlPlugin, sampleAiPlugin)); + + Datasource sampleDatasource = new Datasource(); + sampleDatasource.setName("sampleDatasource"); + sampleDatasource.setPluginId("samplePluginId"); + when(mockDatasourceService.getAllWithStorages(any())).thenReturn(Flux.just(sampleDatasource)); + + Map> sampleFormConfig = new HashMap<>(); + sampleFormConfig.put("key", Map.of()); + when(mockPluginService.getFormConfig(anyString())).thenReturn(Mono.just(sampleFormConfig)); + + MockDataSet sampleMockDataSet = new MockDataSet(); + sampleMockDataSet.setName("sampleMockDataSet"); + MockDataDTO sampleMockDataDTO = new MockDataDTO(); + sampleMockDataDTO.setMockdbs(List.of(sampleMockDataSet)); + when(mockMockDataService.getMockDataSet()).thenReturn(Mono.just(sampleMockDataDTO)); + + Mono consolidatedInfoForPageLoad = + consolidatedAPIService.getConsolidatedInfoForPageLoad("pageId", null, null, ApplicationMode.EDIT); + StepVerifier.create(consolidatedInfoForPageLoad) + .assertNext(consolidatedAPIResponseDTO -> { + assertNotNull(consolidatedAPIResponseDTO.getUserProfile()); + assertEquals( + "sampleUserProfileDTO", + consolidatedAPIResponseDTO + .getUserProfile() + .getData() + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getTenantConfig()); + assertEquals( + "sampleTenant", + consolidatedAPIResponseDTO + .getTenantConfig() + .getData() + .getDisplayName()); + + assertNotNull(consolidatedAPIResponseDTO.getFeatureFlags()); + assertTrue(consolidatedAPIResponseDTO + .getFeatureFlags() + .getData() + .get("sampleFeatureFlag")); + + assertNotNull(consolidatedAPIResponseDTO.getCurrentTheme()); + assertEquals( + "sampleTheme", + consolidatedAPIResponseDTO + .getCurrentTheme() + .getData() + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getThemes()); + assertEquals( + 1, consolidatedAPIResponseDTO.getThemes().getData().size()); + assertEquals( + "sampleTheme", + consolidatedAPIResponseDTO + .getThemes() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getCustomJSLibraries()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getCustomJSLibraries() + .getData() + .size()); + assertEquals( + "sampleJSLib", + consolidatedAPIResponseDTO + .getCustomJSLibraries() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getProductAlert()); + assertEquals( + "sampleProductAlert", + consolidatedAPIResponseDTO + .getProductAlert() + .getData() + .getTitle()); + + assertNotNull(consolidatedAPIResponseDTO.getUnpublishedActions()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getUnpublishedActions() + .getData() + .size()); + assertEquals( + "sampleActionDTO", + consolidatedAPIResponseDTO + .getUnpublishedActions() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getUnpublishedActionCollections()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getUnpublishedActionCollections() + .getData() + .size()); + assertEquals( + "sampleActionCollectionDTO", + consolidatedAPIResponseDTO + .getUnpublishedActionCollections() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getPagesWithMigratedDsl()); + assertNotNull(consolidatedAPIResponseDTO.getUnpublishedActions()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getUnpublishedActions() + .getData() + .size()); + assertNotNull(consolidatedAPIResponseDTO + .getUnpublishedActions() + .getData() + .get(0) + .getUpdatedAt()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getPagesWithMigratedDsl() + .getData() + .size()); + assertEquals( + "samplePageDTO", + consolidatedAPIResponseDTO + .getPagesWithMigratedDsl() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getPlugins()); + assertEquals( + 4, consolidatedAPIResponseDTO.getPlugins().getData().size()); + List pluginPackageNameList = consolidatedAPIResponseDTO.getPlugins().getData().stream() + .map(Plugin::getPackageName) + .toList(); + assertTrue(pluginPackageNameList.contains(REST_API_PLUGIN)); + assertTrue(pluginPackageNameList.contains(GRAPHQL_PLUGIN)); + assertTrue(pluginPackageNameList.contains(APPSMITH_AI_PLUGIN)); + + assertNotNull(consolidatedAPIResponseDTO.getPluginFormConfigs()); + assertEquals( + 4, + consolidatedAPIResponseDTO + .getPluginFormConfigs() + .getData() + .keySet() + .size()); + assertTrue(consolidatedAPIResponseDTO + .getPluginFormConfigs() + .getData() + .containsKey("samplePluginId")); + assertTrue(consolidatedAPIResponseDTO + .getPluginFormConfigs() + .getData() + .containsKey("sampleRestApiPluginId")); + assertTrue(consolidatedAPIResponseDTO + .getPluginFormConfigs() + .getData() + .containsKey("sampleGraphqlPluginId")); + assertTrue(consolidatedAPIResponseDTO + .getPluginFormConfigs() + .getData() + .containsKey("sampleAiPluginId")); + + assertNotNull(consolidatedAPIResponseDTO.getMockDatasources()); + assertEquals( + 1, + consolidatedAPIResponseDTO + .getMockDatasources() + .getData() + .size()); + assertEquals( + "sampleMockDataSet", + consolidatedAPIResponseDTO + .getMockDatasources() + .getData() + .get(0) + .getName()); + + assertNotNull(consolidatedAPIResponseDTO.getPages()); + assertEquals( + "defaultApplicationId", + consolidatedAPIResponseDTO + .getPages() + .getData() + .getApplication() + .getId()); + }) + .verifyComplete(); + } }