-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: CGS commit and detach negative tests (#38173)
## Description > [!TIP] > _Add a TL;DR when the description is longer than 500 words or extremely technical (helps the content, marketing, and DevRel team)._ > > _Please also include relevant motivation and context. List any dependencies that are required for this change. Add links to Notion, Figma or any other documents that might be relevant to the PR._ Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!WARNING] > Tests have not run on the HEAD c7743a7 yet > <hr>Mon, 16 Dec 2024 07:21:41 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced unit tests for Git commit functionality, covering scenarios such as empty commit messages and invalid configurations. - Added unit tests for Git detach functionality, validating error handling and permission checks. - **Tests** - New test classes created to enhance testing coverage for Git operations. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Loading branch information
1 parent
016e30b
commit a3e9967
Showing
2 changed files
with
368 additions
and
0 deletions.
There are no files selected for viewing
237 changes: 237 additions & 0 deletions
237
app/server/appsmith-server/src/test/java/com/appsmith/server/git/ops/GitCommitTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
package com.appsmith.server.git.ops; | ||
|
||
import com.appsmith.external.git.handler.FSGitHandler; | ||
import com.appsmith.git.dto.CommitDTO; | ||
import com.appsmith.server.applications.base.ApplicationService; | ||
import com.appsmith.server.constants.ArtifactType; | ||
import com.appsmith.server.domains.Application; | ||
import com.appsmith.server.domains.GitArtifactMetadata; | ||
import com.appsmith.server.domains.GitAuth; | ||
import com.appsmith.server.domains.GitProfile; | ||
import com.appsmith.server.domains.User; | ||
import com.appsmith.server.domains.Workspace; | ||
import com.appsmith.server.dtos.GitConnectDTO; | ||
import com.appsmith.server.dtos.PageDTO; | ||
import com.appsmith.server.exceptions.AppsmithError; | ||
import com.appsmith.server.exceptions.AppsmithException; | ||
import com.appsmith.server.git.central.CentralGitService; | ||
import com.appsmith.server.git.central.GitType; | ||
import com.appsmith.server.helpers.CommonGitFileUtils; | ||
import com.appsmith.server.services.ApplicationPageService; | ||
import com.appsmith.server.services.UserService; | ||
import com.appsmith.server.services.WorkspaceService; | ||
import org.apache.commons.lang.StringUtils; | ||
import org.eclipse.jgit.api.errors.EmptyCommitException; | ||
import org.eclipse.jgit.errors.RepositoryNotFoundException; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.TestInstance; | ||
import org.mockito.Mockito; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.boot.test.mock.mockito.SpyBean; | ||
import org.springframework.security.test.context.support.WithUserDetails; | ||
import reactor.core.publisher.Mono; | ||
import reactor.test.StepVerifier; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.UUID; | ||
|
||
import static com.appsmith.external.git.constants.GitConstants.EMPTY_COMMIT_ERROR_MESSAGE; | ||
import static com.appsmith.external.git.constants.GitConstants.GIT_CONFIG_ERROR; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.mockito.ArgumentMatchers.any; | ||
|
||
@SpringBootTest | ||
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | ||
public class GitCommitTests { | ||
|
||
@Autowired | ||
CentralGitService centralGitService; | ||
|
||
@Autowired | ||
ApplicationPageService applicationPageService; | ||
|
||
@Autowired | ||
ApplicationService applicationService; | ||
|
||
@Autowired | ||
WorkspaceService workspaceService; | ||
|
||
@Autowired | ||
UserService userService; | ||
|
||
@SpyBean | ||
FSGitHandler fsGitHandler; | ||
|
||
@SpyBean | ||
CommonGitFileUtils commonGitFileUtils; | ||
|
||
@Test | ||
@WithUserDetails(value = "api_user") | ||
public void commitArtifact_whenNoChangesInLocal_returnsWithEmptyCommitMessage() throws IOException { | ||
|
||
CommitDTO commitDTO = new CommitDTO(); | ||
commitDTO.setMessage("empty commit"); | ||
|
||
User apiUser = userService.findByEmail("api_user").block(); | ||
Workspace toCreate = new Workspace(); | ||
toCreate.setName("Workspace_" + UUID.randomUUID()); | ||
Workspace workspace = | ||
workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); | ||
assertThat(workspace).isNotNull(); | ||
|
||
Application application = | ||
createApplicationConnectedToGit("Application_" + UUID.randomUUID(), "foo", workspace.getId()); | ||
|
||
Mockito.doReturn(Mono.just(Paths.get(""))) | ||
.when(commonGitFileUtils) | ||
.saveArtifactToLocalRepoWithAnalytics(any(Path.class), any(), Mockito.anyString()); | ||
Mockito.doReturn(Mono.error(new EmptyCommitException("nothing to commit"))) | ||
.when(fsGitHandler) | ||
.commitArtifact( | ||
any(Path.class), | ||
Mockito.anyString(), | ||
Mockito.anyString(), | ||
Mockito.anyString(), | ||
Mockito.anyBoolean(), | ||
Mockito.anyBoolean()); | ||
|
||
Mono<String> commitMono = centralGitService.commitArtifact( | ||
commitDTO, application.getId(), ArtifactType.APPLICATION, GitType.FILE_SYSTEM); | ||
|
||
StepVerifier.create(commitMono) | ||
.assertNext(commitMsg -> { | ||
assertThat(commitMsg).contains(EMPTY_COMMIT_ERROR_MESSAGE); | ||
}) | ||
.verifyComplete(); | ||
} | ||
|
||
private Application createApplicationConnectedToGit(String name, String branchName, String workspaceId) | ||
throws IOException { | ||
|
||
if (StringUtils.isEmpty(branchName)) { | ||
branchName = "foo"; | ||
} | ||
Mockito.doReturn(Mono.just(branchName)) | ||
.when(fsGitHandler) | ||
.cloneRemoteIntoArtifactRepo(any(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString()); | ||
Mockito.doReturn(Mono.just("commit")) | ||
.when(fsGitHandler) | ||
.commitArtifact( | ||
any(Path.class), | ||
Mockito.anyString(), | ||
Mockito.anyString(), | ||
Mockito.anyString(), | ||
Mockito.anyBoolean(), | ||
Mockito.anyBoolean()); | ||
Mockito.doReturn(Mono.just(true)).when(fsGitHandler).checkoutToBranch(any(Path.class), Mockito.anyString()); | ||
Mockito.doReturn(Mono.just("success")) | ||
.when(fsGitHandler) | ||
.pushApplication(any(Path.class), any(), any(), any(), any()); | ||
Mockito.doReturn(Mono.just(true)).when(commonGitFileUtils).checkIfDirectoryIsEmpty(any(Path.class)); | ||
Mockito.doReturn(Mono.just(Paths.get("textPath"))) | ||
.when(commonGitFileUtils) | ||
.initializeReadme(any(Path.class), Mockito.anyString(), Mockito.anyString()); | ||
Mockito.doReturn(Mono.just(Paths.get("path"))) | ||
.when(commonGitFileUtils) | ||
.saveArtifactToLocalRepoWithAnalytics(any(Path.class), any(), Mockito.anyString()); | ||
|
||
Application testApplication = new Application(); | ||
testApplication.setName(name); | ||
testApplication.setWorkspaceId(workspaceId); | ||
Application application1 = | ||
applicationPageService.createApplication(testApplication).block(); | ||
|
||
GitArtifactMetadata gitArtifactMetadata = new GitArtifactMetadata(); | ||
GitAuth gitAuth = new GitAuth(); | ||
gitAuth.setPublicKey("testkey"); | ||
gitAuth.setPrivateKey("privatekey"); | ||
gitArtifactMetadata.setGitAuth(gitAuth); | ||
gitArtifactMetadata.setDefaultApplicationId(application1.getId()); | ||
gitArtifactMetadata.setRepoName("testRepo"); | ||
application1.setGitApplicationMetadata(gitArtifactMetadata); | ||
application1 = applicationService.save(application1).block(); | ||
|
||
PageDTO page = new PageDTO(); | ||
page.setName("New Page"); | ||
page.setApplicationId(application1.getId()); | ||
applicationPageService.createPage(page).block(); | ||
|
||
GitProfile gitProfile = new GitProfile(); | ||
gitProfile.setAuthorEmail("test@email.com"); | ||
gitProfile.setAuthorName("testUser"); | ||
GitConnectDTO gitConnectDTO = new GitConnectDTO(); | ||
gitConnectDTO.setRemoteUrl("git@github.com:test/testRepo.git"); | ||
gitConnectDTO.setGitProfile(gitProfile); | ||
return centralGitService | ||
.connectArtifactToGit( | ||
application1.getId(), gitConnectDTO, "baseUrl", ArtifactType.APPLICATION, GitType.FILE_SYSTEM) | ||
.map(artifact -> (Application) artifact) | ||
.block(); | ||
} | ||
|
||
@Test | ||
@WithUserDetails(value = "api_user") | ||
public void commitArtifact_whenApplicationNotConnectedToGit_throwsInvalidGitConfigException() { | ||
|
||
User apiUser = userService.findByEmail("api_user").block(); | ||
Workspace toCreate = new Workspace(); | ||
toCreate.setName("Workspace_" + UUID.randomUUID()); | ||
Workspace workspace = | ||
workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); | ||
assertThat(workspace).isNotNull(); | ||
|
||
Application application = new Application(); | ||
application.setName("sampleAppNotConnectedToGit"); | ||
application.setWorkspaceId(workspace.getId()); | ||
application.setId(null); | ||
application = applicationPageService.createApplication(application).block(); | ||
|
||
CommitDTO commitDTO = new CommitDTO(); | ||
commitDTO.setMessage("empty commit"); | ||
|
||
Mono<String> commitMono = centralGitService.commitArtifact( | ||
commitDTO, application.getId(), ArtifactType.APPLICATION, GitType.FILE_SYSTEM); | ||
|
||
StepVerifier.create(commitMono) | ||
.expectErrorMatches(throwable -> throwable instanceof AppsmithException | ||
&& throwable | ||
.getMessage() | ||
.equals(AppsmithError.INVALID_GIT_CONFIGURATION.getMessage(GIT_CONFIG_ERROR))) | ||
.verify(); | ||
} | ||
|
||
@Test | ||
@WithUserDetails(value = "api_user") | ||
public void commitArtifact_whenLocalRepoNotAvailable_throwsRepoNotFoundException() throws IOException { | ||
|
||
CommitDTO commitDTO = new CommitDTO(); | ||
commitDTO.setMessage("empty commit"); | ||
|
||
User apiUser = userService.findByEmail("api_user").block(); | ||
Workspace toCreate = new Workspace(); | ||
toCreate.setName("Workspace_" + UUID.randomUUID()); | ||
Workspace workspace = | ||
workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); | ||
assertThat(workspace).isNotNull(); | ||
|
||
Application application = | ||
createApplicationConnectedToGit("Application_" + UUID.randomUUID(), "foo", workspace.getId()); | ||
|
||
Mono<String> commitMono = centralGitService.commitArtifact( | ||
commitDTO, application.getId(), ArtifactType.APPLICATION, GitType.FILE_SYSTEM); | ||
|
||
Mockito.doReturn(Mono.error(new RepositoryNotFoundException(AppsmithError.REPOSITORY_NOT_FOUND.getMessage()))) | ||
.when(commonGitFileUtils) | ||
.saveArtifactToLocalRepoWithAnalytics(any(Path.class), any(), Mockito.anyString()); | ||
|
||
StepVerifier.create(commitMono) | ||
.expectErrorMatches(throwable -> throwable instanceof AppsmithException | ||
&& throwable | ||
.getMessage() | ||
.contains(AppsmithError.REPOSITORY_NOT_FOUND.getMessage(application.getId()))) | ||
.verify(); | ||
} | ||
} |
131 changes: 131 additions & 0 deletions
131
app/server/appsmith-server/src/test/java/com/appsmith/server/git/ops/GitDetachTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package com.appsmith.server.git.ops; | ||
|
||
import com.appsmith.external.git.handler.FSGitHandler; | ||
import com.appsmith.server.acl.AclPermission; | ||
import com.appsmith.server.constants.ArtifactType; | ||
import com.appsmith.server.constants.FieldName; | ||
import com.appsmith.server.domains.Application; | ||
import com.appsmith.server.domains.User; | ||
import com.appsmith.server.domains.Workspace; | ||
import com.appsmith.server.exceptions.AppsmithError; | ||
import com.appsmith.server.exceptions.AppsmithException; | ||
import com.appsmith.server.git.central.CentralGitService; | ||
import com.appsmith.server.git.central.GitType; | ||
import com.appsmith.server.helpers.CommonGitFileUtils; | ||
import com.appsmith.server.repositories.ApplicationRepository; | ||
import com.appsmith.server.services.ApplicationPageService; | ||
import com.appsmith.server.services.UserService; | ||
import com.appsmith.server.services.WorkspaceService; | ||
import com.appsmith.server.solutions.ApplicationPermission; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.TestInstance; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.boot.test.mock.mockito.SpyBean; | ||
import org.springframework.security.test.context.support.WithUserDetails; | ||
import reactor.core.publisher.Mono; | ||
import reactor.test.StepVerifier; | ||
|
||
import java.util.UUID; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
@SpringBootTest | ||
@TestInstance(TestInstance.Lifecycle.PER_CLASS) | ||
public class GitDetachTests { | ||
|
||
@Autowired | ||
CentralGitService centralGitService; | ||
|
||
@Autowired | ||
ApplicationPageService applicationPageService; | ||
|
||
@Autowired | ||
WorkspaceService workspaceService; | ||
|
||
@Autowired | ||
UserService userService; | ||
|
||
@Autowired | ||
ApplicationPermission applicationPermission; | ||
|
||
@Autowired | ||
ApplicationRepository applicationRepository; | ||
|
||
@SpyBean | ||
FSGitHandler fsGitHandler; | ||
|
||
@SpyBean | ||
CommonGitFileUtils commonGitFileUtils; | ||
|
||
@Test | ||
@WithUserDetails(value = "api_user") | ||
public void detachRemote_withEmptyGitData_hasNoChangeOnArtifact() { | ||
User apiUser = userService.findByEmail("api_user").block(); | ||
Workspace toCreate = new Workspace(); | ||
toCreate.setName("Workspace_" + UUID.randomUUID()); | ||
Workspace workspace = | ||
workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); | ||
assertThat(workspace).isNotNull(); | ||
|
||
Application testApplication = new Application(); | ||
testApplication.setGitApplicationMetadata(null); | ||
testApplication.setName("detachRemote_withEmptyGitData"); | ||
testApplication.setWorkspaceId(workspace.getId()); | ||
Application application1 = | ||
applicationPageService.createApplication(testApplication).block(); | ||
|
||
Mono<Application> applicationMono = centralGitService | ||
.detachRemote(application1.getId(), ArtifactType.APPLICATION, GitType.FILE_SYSTEM) | ||
.map(artifact -> (Application) artifact); | ||
|
||
StepVerifier.create(applicationMono) | ||
.expectErrorMatches(throwable -> throwable instanceof AppsmithException | ||
& throwable.getMessage().contains("Git configuration is invalid")) | ||
.verify(); | ||
} | ||
|
||
@WithUserDetails("api_user") | ||
@Test | ||
public void detachRemote_whenUserDoesNotHaveRequiredPermission_throwsException() { | ||
Application application = | ||
createApplicationAndRemovePermissionFromApplication(applicationPermission.getGitConnectPermission()); | ||
Mono<Application> applicationMono = centralGitService | ||
.detachRemote(application.getId(), ArtifactType.APPLICATION, GitType.FILE_SYSTEM) | ||
.map(artifact -> (Application) artifact); | ||
|
||
StepVerifier.create(applicationMono) | ||
.expectErrorMessage( | ||
AppsmithError.ACL_NO_RESOURCE_FOUND.getMessage(FieldName.APPLICATION, application.getId())) | ||
.verify(); | ||
} | ||
|
||
/** | ||
* This method creates a workspace, creates an application in the workspace and removes the | ||
* create application permission from the workspace for the api_user. | ||
* | ||
* @return Created Application | ||
*/ | ||
private Application createApplicationAndRemovePermissionFromApplication(AclPermission permission) { | ||
User apiUser = userService.findByEmail("api_user").block(); | ||
|
||
Workspace toCreate = new Workspace(); | ||
toCreate.setName("Workspace_" + UUID.randomUUID()); | ||
Workspace workspace = | ||
workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); | ||
assertThat(workspace).isNotNull(); | ||
|
||
Application testApplication = new Application(); | ||
testApplication.setWorkspaceId(workspace.getId()); | ||
testApplication.setName("Test App"); | ||
Application application1 = | ||
applicationPageService.createApplication(testApplication).block(); | ||
|
||
assertThat(application1).isNotNull(); | ||
|
||
// remove permission from the application for the api user | ||
application1.getPolicyMap().remove(permission.getValue()); | ||
|
||
return applicationRepository.save(application1).block(); | ||
} | ||
} |