diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationFetcherCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationFetcherCEImpl.java index 15d8e40288..0f86730f82 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationFetcherCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationFetcherCEImpl.java @@ -112,9 +112,15 @@ public class ApplicationFetcherCEImpl implements ApplicationFetcherCE { // Collect all the applications as a map with organization id as a key Flux applicationFlux = applicationRepository .findByMultipleOrganizationIds(orgIds, READ_APPLICATIONS) + // Git connected apps will have gitApplicationMetadat .filter(application -> application.getGitApplicationMetadata() == null - || (!StringUtils.isEmpty(application.getGitApplicationMetadata().getDefaultBranchName()) - && application.getGitApplicationMetadata().getBranchName().equals(application.getGitApplicationMetadata().getDefaultBranchName())) + // 1. When the ssh key is generated by user and then the connect app fails + || (StringUtils.isEmpty(application.getGitApplicationMetadata().getDefaultBranchName()) + && StringUtils.isEmpty(application.getGitApplicationMetadata().getBranchName())) + // 2. When the DefaultBranchName is missing due to branch creation flow failures or corrupted scenarios + || (!StringUtils.isEmpty(application.getGitApplicationMetadata().getBranchName()) + && application.getGitApplicationMetadata().getBranchName().equals(application.getGitApplicationMetadata().getDefaultBranchName()) + ) ) .map(responseUtils::updateApplicationWithDefaultResources); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationFetcherUnitTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationFetcherUnitTest.java index a81f655cd6..fa42f4a5b7 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationFetcherUnitTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationFetcherUnitTest.java @@ -2,14 +2,18 @@ package com.appsmith.server.solutions; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.ApplicationPage; +import com.appsmith.server.domains.GitApplicationMetadata; +import com.appsmith.server.domains.GitAuth; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; import com.appsmith.server.dtos.OrganizationApplicationsDTO; import com.appsmith.server.dtos.PageDTO; +import com.appsmith.server.dtos.UserHomepageDTO; import com.appsmith.server.helpers.ResponseUtils; import com.appsmith.server.repositories.ApplicationRepository; +import com.appsmith.server.services.ApplicationService; import com.appsmith.server.services.NewPageService; import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; @@ -18,7 +22,9 @@ import com.appsmith.server.services.UserService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; import reactor.core.publisher.Flux; @@ -65,6 +71,9 @@ public class ApplicationFetcherUnitTest { ApplicationFetcher applicationFetcher; + @MockBean + ApplicationService applicationService; + User testUser; final static String defaultPageId = "defaultPageId"; @@ -194,6 +203,9 @@ public class ApplicationFetcherUnitTest { .thenReturn(updateDefaultPageIdsWithinApplication(application)); } + Mockito.when(applicationService.createOrUpdateSshKeyPair(Mockito.anyString())) + .thenReturn(Mono.just(new GitAuth())); + StepVerifier.create(applicationFetcher.getAllApplications()) .assertNext(userHomepageDTO -> { List dtos = userHomepageDTO.getOrganizationApplications(); @@ -213,6 +225,140 @@ public class ApplicationFetcherUnitTest { }).verifyComplete(); } + @Test + public void getAllApplications_gitConnectedAppScenarios_OnlyTheDefaultBranchedAppIsReturned() { + initMocks(); + // mock the user data to return recently used orgs and apps + UserData userData = new UserData(); + Mockito.when(userDataService.getForCurrentUser()).thenReturn(Mono.just(userData)); + + // mock the list of applications + List applications = createDummyApplications(4,4); + List pageList = createDummyPages(4, 4); + + Mockito.when(applicationRepository.findByMultipleOrganizationIds( + testUser.getOrganizationIds(), READ_APPLICATIONS) + ).thenReturn(Flux.fromIterable(applications)); + + Mockito.when(newPageService.findPageSlugsByApplicationIds(anyList(), eq(READ_PAGES))) + .thenReturn(Flux.fromIterable(pageList)); + + for (Application application : applications) { + Mockito + .when(responseUtils.updateApplicationWithDefaultResources(application)) + .thenReturn(updateDefaultPageIdsWithinApplication(application)); + } + + Mockito.when(applicationService.createOrUpdateSshKeyPair(Mockito.anyString())) + .thenReturn(Mono.just(new GitAuth())); + + StepVerifier.create(applicationFetcher.getAllApplications()) + .assertNext(userHomepageDTO -> { + List dtos = userHomepageDTO.getOrganizationApplications(); + assertThat(dtos.size()).isEqualTo(4); + for (OrganizationApplicationsDTO dto : dtos) { + assertThat(dto.getApplications().size()).isEqualTo(4); + List applicationList = dto.getApplications(); + for (Application application : applicationList) { + application.getPages().forEach( + page -> assertThat(page.getSlug()).isEqualTo(page.getId()+"-unpublished-slug") + ); + application.getPublishedPages().forEach( + page -> assertThat(page.getSlug()).isEqualTo(page.getId()+"-published-slug") + ); + } + } + }).verifyComplete(); + + // Generate SSH keys for an app - to test if the app is visible in home page when the git connect step is aborted in middle + Mockito.when(applicationService.save(Mockito.any(Application.class))) + .thenReturn(Mono.just(new Application())); + Mono userHomepageDTOMono = applicationFetcher.getAllApplications() + .flatMap(userHomepageDTO -> { + List dtos = userHomepageDTO.getOrganizationApplications(); + List applicationList = dtos.get(0).getApplications(); + return Mono.just(applicationList.get(0)); + }) + // After choosing the any app randomly to connect to git, Generate keys and stop the process + .flatMap(application -> applicationService.createOrUpdateSshKeyPair(application.getId())) + .then(applicationFetcher.getAllApplications()); + + StepVerifier.create(userHomepageDTOMono) + .assertNext(userHomepageDTO -> { + List dtos = userHomepageDTO.getOrganizationApplications(); + assertThat(dtos.size()).isEqualTo(4); + for (OrganizationApplicationsDTO dto : dtos) { + assertThat(dto.getApplications().size()).isEqualTo(4); + List applicationList = dto.getApplications(); + for (Application application : applicationList) { + application.getPages().forEach( + page -> assertThat(page.getSlug()).isEqualTo(page.getId()+"-unpublished-slug") + ); + application.getPublishedPages().forEach( + page -> assertThat(page.getSlug()).isEqualTo(page.getId()+"-published-slug") + ); + } + } + }).verifyComplete(); + + // For connect and create branch flow scenarios where - defaultBranchName is somehow not saved in DB + userHomepageDTOMono = applicationFetcher.getAllApplications() + .flatMap(userHomepageDTO -> { + List dtos = userHomepageDTO.getOrganizationApplications(); + List applicationList = dtos.get(0).getApplications(); + return Mono.just(applicationList.get(0)); + }) + .flatMap(application -> { + // Create a new branched App resource in the same org and verify that branch App does not show up in the response. + Application branchApp = new Application(); + branchApp.setName("branched App"); + branchApp.setOrganizationId(application.getOrganizationId()); + branchApp.setId("org-" + 5 + "-app-" + 5); + GitApplicationMetadata gitApplicationMetadata = new GitApplicationMetadata(); + gitApplicationMetadata.setDefaultApplicationId(application.getId()); + gitApplicationMetadata.setBranchName("master"); + gitApplicationMetadata.setRemoteUrl("remnoteUrl"); + branchApp.setGitApplicationMetadata(gitApplicationMetadata); + + // Set dummy applicationPages + ApplicationPage unpublishedPage = new ApplicationPage(); + unpublishedPage.setId("page" + 5); + unpublishedPage.setDefaultPageId("page" + 5); + unpublishedPage.setIsDefault(true); + + ApplicationPage publishedPage = new ApplicationPage(); + publishedPage.setId("page" + 5); + publishedPage.setDefaultPageId("page" + 5); + publishedPage.setIsDefault(true); + + branchApp.setPages(List.of(unpublishedPage)); + branchApp.setPublishedPages(List.of(publishedPage)); + applications.add(branchApp); + + return applicationService.save(branchApp); + }) + .then(applicationFetcher.getAllApplications()); + + StepVerifier.create(userHomepageDTOMono) + .assertNext(userHomepageDTO -> { + List dtos = userHomepageDTO.getOrganizationApplications(); + assertThat(dtos.size()).isEqualTo(4); + for (OrganizationApplicationsDTO dto : dtos) { + assertThat(dto.getApplications().size()).isEqualTo(4); + List applicationList = dto.getApplications(); + for (Application application : applicationList) { + application.getPages().forEach( + page -> assertThat(page.getSlug()).isEqualTo(page.getId()+"-unpublished-slug") + ); + application.getPublishedPages().forEach( + page -> assertThat(page.getSlug()).isEqualTo(page.getId()+"-published-slug") + ); + } + } + }).verifyComplete(); + + } + @Test public void getAllApplications_WhenUserHasRecentOrgAndApp_RecentEntriesComeFirst() { initMocks();