src/integrationTests/kotlin/IRGitPlatformTest.kt (145 lines of code) (raw):
package com.jetbrains.interactiveRebase.integrationTests
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.service
import com.intellij.openapi.vcs.Executor.overwrite
import com.intellij.openapi.vcs.Executor.touch
import com.intellij.testFramework.TestActionEvent.createTestEvent
import com.intellij.testFramework.common.runAll
import com.intellij.testFramework.replaceService
import com.intellij.vcs.test.VcsPlatformTest
import com.jetbrains.interactiveRebase.actions.CreateEditorTabAction
import com.jetbrains.interactiveRebase.integrationTests.git4ideaTestClasses.IRTestGitImpl
import com.jetbrains.interactiveRebase.integrationTests.git4ideaTestClasses.addCommit
import com.jetbrains.interactiveRebase.integrationTests.git4ideaTestClasses.assumeSupportedGitVersion
import com.jetbrains.interactiveRebase.integrationTests.git4ideaTestClasses.checkoutNew
import com.jetbrains.interactiveRebase.integrationTests.git4ideaTestClasses.createRepository
import com.jetbrains.interactiveRebase.integrationTests.git4ideaTestClasses.git
import com.jetbrains.interactiveRebase.integrationTests.git4ideaTestClasses.gitExecutable
import com.jetbrains.interactiveRebase.services.ActionService
import com.jetbrains.interactiveRebase.services.ModelService
import com.jetbrains.interactiveRebase.visuals.RoundedButton
import git4idea.GitVcs
import git4idea.commands.Git
import git4idea.config.GitExecutableManager
import git4idea.config.GitVcsApplicationSettings
import git4idea.config.GitVcsSettings
import git4idea.repo.GitRepository
import git4idea.repo.GitRepositoryManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import org.assertj.core.api.AssertionsForClassTypes.assertThat
import org.awaitility.Awaitility
import org.junit.jupiter.api.TestInstance
import java.util.concurrent.TimeUnit
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
abstract class IRGitPlatformTest : VcsPlatformTest() {
lateinit var git: IRTestGitImpl
lateinit var repository: GitRepository
lateinit var repositoryManager: GitRepositoryManager
lateinit var vcs: GitVcs
lateinit var settings: GitVcsSettings
lateinit var appSettings: GitVcsApplicationSettings
var developmentBranch: String = "development"
lateinit var initialCommitOnMain: String
lateinit var firstCommitOnDev: String
lateinit var secondCommitOnDev: String
lateinit var thirdCommitOnDev: String
lateinit var fourthCommitOnDev: String
lateinit var checkedOutBranch: String
/**
* Setup method that:
*
* - creates a repository
* - makes the branch "main" the default one
* - makes an initial commit
* - checks out the "development" branch
* - creates a file and commits it
*/
@Throws(Exception::class)
override fun setUp() {
System.setProperty("test.mode", "false")
super.setUp()
git = IRTestGitImpl()
ApplicationManager.getApplication().replaceService(Git::class.java, git, testRootDisposable)
repositoryManager = GitRepositoryManager.getInstance(project)
vcs = GitVcs.getInstance(project)
vcs.doActivate()
settings = GitVcsSettings.getInstance(project)
appSettings = GitVcsApplicationSettings.getInstance()
appSettings.setPathToGit(gitExecutable())
GitExecutableManager.getInstance().testGitExecutableVersionValid(project)
assumeSupportedGitVersion(vcs)
runBlocking(Dispatchers.IO) {
// This creates a new repository in the test project root
repository = createRepository(project, projectNioRoot, true)
git("config --global init.defaultBranch main")
initialCommitOnMain = git("rev-list --max-parents=0 HEAD")
// This creates a new branch called "development",
// and leaves the state to the new branch (checked out on branch "development")
repository.checkoutNew(developmentBranch)
assertCorrectCheckedOutBranch(developmentBranch)
firstCommitOnDev = createAndCommitNewFile("file1.txt", "first")
secondCommitOnDev = createAndCommitNewFile("file2.txt", "code quality")
thirdCommitOnDev = createAndCommitNewFile("file3.txt", "i love testing")
fourthCommitOnDev = createAndCommitNewFile("file4.txt", "my final commit")
Awaitility.await()
.alias("setup has 4 commits")
.pollInSameThread()
.atMost(10000, TimeUnit.MILLISECONDS)
.pollDelay(50, TimeUnit.MILLISECONDS)
.until { gitCommitsCountEquals(4) }
}
}
override fun tearDown() {
runAll(
{ if (::git.isInitialized) git.reset() },
{ if (::settings.isInitialized) settings.appSettings.setPathToGit(null) },
{ super.tearDown() },
)
}
/**
* Debugging method that allows to see all commits in the checked out branch.
*/
fun GitRepository.getAllCommitMessages(): List<String> =
git(project, "log --pretty=format:%s")
.lines()
.filter { it.isNotBlank() }
fun GitRepository.getCheckedOutBranch(): String {
return git(project, "rev-parse --abbrev-ref HEAD")
}
fun createAndCommitNewFile(
fileName: String,
commitMessage: String,
): String {
touch(fileName)
git(project, "add $fileName")
return addCommit(commitMessage)
}
private fun modifyAndCommitFile(
fileName: String,
commitMessage: String,
): String {
overwrite(fileName, "content" + Math.random())
return addCommit(commitMessage)
}
fun countCommitsSinceInitialCommit(): Int {
val result = repository.git("rev-list --count " + initialCommitOnMain + "..HEAD")
Thread.sleep(10)
return result.toInt()
}
fun gitCommitsCountEquals(expectedCount: Int): Boolean {
return countCommitsSinceInitialCommit() == expectedCount
}
open fun openAndInitializePlugin(expectedCount: Int = 4) {
assertCorrectCheckedOutBranch(developmentBranch)
val openEditorTabAction = CreateEditorTabAction()
val testEvent = createTestEvent(openEditorTabAction)
assertThat(testEvent.project).isEqualTo(project)
openEditorTabAction.actionPerformed(testEvent)
val modelService = project.service<ModelService>()
Awaitility.await()
.atMost(15000, TimeUnit.MILLISECONDS)
.pollDelay(50, TimeUnit.MILLISECONDS)
.until { modelService.branchInfo.initialCommits.size == expectedCount }
assertThat(modelService.branchInfo.name).isEqualTo(developmentBranch)
}
internal fun assertCorrectCheckedOutBranch(branchName: String) {
checkedOutBranch = repository.getCheckedOutBranch()
assertThat(checkedOutBranch).isEqualTo(branchName)
}
internal fun getRebaseButton(): RoundedButton {
val headerPanel = project.service<ActionService>().getHeaderPanel()
val changesActionsPanel = headerPanel.changeActionsPanel
return changesActionsPanel.components[2] as RoundedButton
}
fun countCommitsSinceSpecificCommit(hash: String): Int {
val result = repository.git("rev-list --count " + hash + "..HEAD")
Thread.sleep(10)
return result.toInt()
}
}