201 lines
9.4 KiB
Kotlin
201 lines
9.4 KiB
Kotlin
package solutions.tretter.githugandroid
|
|
|
|
import org.junit.Assert.assertEquals
|
|
import org.junit.Assert.assertFalse
|
|
import org.junit.Assert.assertTrue
|
|
import org.junit.Test
|
|
|
|
class InteractiveAddEngineTest {
|
|
@Test
|
|
fun interactiveStageShowsMenuWithoutStagingOrAutoCommands() {
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README")))
|
|
|
|
val (updatedRepo, output) = GitSandboxEngine.execute(repo, "git stage -i")
|
|
|
|
assertFalse(updatedRepo.files.single { it.name == "README" }.staged)
|
|
assertTrue(output.any { it.contains("What now>") })
|
|
assertFalse(output.any { it.contains("What now> update") })
|
|
assertFalse(output.any { it.contains("What now> quit") })
|
|
assertFalse(output.any { it.contains("GitHug Android") })
|
|
}
|
|
|
|
@Test
|
|
fun interactiveAddShowsMenuWithoutStagingOrAutoCommands() {
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README")))
|
|
|
|
val (updatedRepo, output) = GitSandboxEngine.execute(repo, "git add -i")
|
|
|
|
assertFalse(updatedRepo.files.single { it.name == "README" }.staged)
|
|
assertTrue(updatedRepo.interactiveAddSession != null)
|
|
assertTrue(output.any { it.contains("What now>") })
|
|
assertFalse(output.any { it.contains("What now> update") })
|
|
assertFalse(output.any { it.contains("What now> quit") })
|
|
}
|
|
|
|
@Test
|
|
fun interactiveAddAcceptsUpdateSelectionFromNextInput() {
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README")))
|
|
|
|
val (menuRepo, _) = GitSandboxEngine.execute(repo, "git stage -i")
|
|
val (updateRepo, updateOutput) = GitSandboxEngine.execute(menuRepo, "2")
|
|
val (selectedRepo, selectionOutput) = GitSandboxEngine.execute(updateRepo, "1")
|
|
val (quitRepo, quitOutput) = GitSandboxEngine.execute(selectedRepo, "7")
|
|
|
|
assertTrue(updateRepo.interactiveAddSession?.awaitingUpdateSelection == true)
|
|
assertTrue(updateOutput.any { it.contains("Update>>") })
|
|
assertTrue(selectedRepo.files.single { it.name == "README" }.staged)
|
|
assertTrue(selectedRepo.interactiveAddSession?.awaitingUpdateSelection == false)
|
|
assertTrue(selectionOutput.any { it.contains("updated 1 path(s)") })
|
|
assertTrue(quitRepo.interactiveAddSession == null)
|
|
assertTrue(quitOutput.any { it.contains("Bye.") })
|
|
}
|
|
|
|
@Test
|
|
fun interactiveAddHandlesEveryDisplayedMenuCommand() {
|
|
val menuCommands = listOf(
|
|
"1" to "What now> 1",
|
|
"2" to "Update>>",
|
|
"3" to "Revert>>",
|
|
"4" to "Add untracked>>",
|
|
"5" to "Patch update>>",
|
|
"6" to "Diff>>",
|
|
"7" to "Bye.",
|
|
"8" to "What now> 8",
|
|
)
|
|
|
|
menuCommands.forEach { (command, expectedOutput) ->
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README")))
|
|
val (menuRepo, _) = GitSandboxEngine.execute(repo, "git add -i")
|
|
val (updatedRepo, output) = GitSandboxEngine.execute(menuRepo, command)
|
|
|
|
assertFalse("$command should not be rejected", output.any { it.contains("Huh ($command)?") })
|
|
assertTrue("$command should produce $expectedOutput", output.any { it.contains(expectedOutput) })
|
|
if (command in listOf("2", "3", "4", "5", "6")) {
|
|
assertTrue(updatedRepo.interactiveAddSession?.awaitingUpdateSelection == true)
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun interactiveAddHandlesMenuCommandAliases() {
|
|
val aliases = listOf(
|
|
"status" to "What now> status",
|
|
"update" to "Update>>",
|
|
"revert" to "Revert>>",
|
|
"add untracked" to "Add untracked>>",
|
|
"patch" to "Patch update>>",
|
|
"diff" to "Diff>>",
|
|
"quit" to "Bye.",
|
|
"help" to "What now> help",
|
|
)
|
|
|
|
aliases.forEach { (command, expectedOutput) ->
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README")))
|
|
val (menuRepo, _) = GitSandboxEngine.execute(repo, "git add -i")
|
|
val (updatedRepo, output) = GitSandboxEngine.execute(menuRepo, command)
|
|
|
|
assertFalse("$command should not be rejected", output.any { it.contains("Huh ($command)?") })
|
|
assertTrue("$command should produce $expectedOutput", output.any { it.contains(expectedOutput) })
|
|
if (command in listOf("update", "revert", "add untracked", "patch", "diff")) {
|
|
assertTrue(updatedRepo.interactiveAddSession?.awaitingUpdateSelection == true)
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun interactiveAddPatchSelectionStagesSelectedPath() {
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README")))
|
|
|
|
val (menuRepo, _) = GitSandboxEngine.execute(repo, "git add -i")
|
|
val (patchRepo, patchOutput) = GitSandboxEngine.execute(menuRepo, "patch")
|
|
val (hunkRepo, hunkOutput) = GitSandboxEngine.execute(patchRepo, "1")
|
|
val (selectedRepo, selectionOutput) = GitSandboxEngine.execute(hunkRepo, "y")
|
|
|
|
assertTrue(patchRepo.interactiveAddSession?.awaitingUpdateSelection == true)
|
|
assertTrue(patchOutput.any { it.contains("Patch update>>") })
|
|
assertTrue(hunkOutput.any { it.contains("Stage this hunk") })
|
|
assertTrue(selectedRepo.files.single { it.name == "README" }.staged)
|
|
assertTrue(selectionOutput.any { it.contains("Stage this hunk") && it.contains("y") })
|
|
}
|
|
|
|
@Test
|
|
fun patchAddStartsPatchHunkDialogWithoutStagingImmediately() {
|
|
listOf("git add -p README", "git add --patch README").forEach { command ->
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README")))
|
|
|
|
val (patchRepo, output) = GitSandboxEngine.execute(repo, command)
|
|
|
|
assertFalse("$command should not stage before a selection", patchRepo.files.single { it.name == "README" }.staged)
|
|
assertEquals("patch-hunk", patchRepo.interactiveAddSession?.selectionAction)
|
|
assertTrue(output.any { it.startsWith("diff --git a/README b/README") })
|
|
assertTrue(output.any { it.contains("Stage this hunk") })
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun patchAddSelectionStagesSelectedPath() {
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README")))
|
|
|
|
val (patchRepo, _) = GitSandboxEngine.execute(repo, "git add -p README")
|
|
val (selectedRepo, output) = GitSandboxEngine.execute(patchRepo, "y")
|
|
|
|
assertTrue(selectedRepo.files.single { it.name == "README" }.staged)
|
|
assertTrue(output.any { it.contains("Stage this hunk") && it.contains("y") })
|
|
assertTrue(selectedRepo.interactiveAddSession == null)
|
|
}
|
|
|
|
@Test
|
|
fun patchAddHunkEditOpensPatchEditorInvocation() {
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README", "A\nB\n", tracked = true)))
|
|
val (patchRepo, _) = GitSandboxEngine.execute(repo, "git add -p README")
|
|
|
|
val invocation = GitSandboxEngine.parsePatchHunkEditorInvocation(patchRepo, "e")
|
|
|
|
assertEquals(GitEditorCommandKind.PATCH_HUNK, invocation?.kind)
|
|
assertEquals("Edit Patch Hunk", invocation?.title)
|
|
assertTrue(invocation?.initialContent.orEmpty().startsWith("# Manual hunk edit mode -- see bottom for a quick guide."))
|
|
assertFalse(invocation?.initialContent.orEmpty().contains("diff --git a/README b/README"))
|
|
assertFalse(invocation?.initialContent.orEmpty().contains("--- a/README"))
|
|
assertTrue(invocation?.initialContent.orEmpty().contains("# ---"))
|
|
assertTrue(invocation?.initialContent.orEmpty().contains("# To remove '+' lines, delete them."))
|
|
assertTrue(invocation?.initialContent.orEmpty().contains("+A"))
|
|
assertFalse(invocation?.initialContent.orEmpty().contains("Stage this hunk"))
|
|
}
|
|
|
|
@Test
|
|
fun editedPatchHunkStagesCurrentPatchTarget() {
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README", "A\nB\n", tracked = true)))
|
|
val (patchRepo, _) = GitSandboxEngine.execute(repo, "git add -p README")
|
|
val invocation = GitSandboxEngine.parsePatchHunkEditorInvocation(patchRepo, "e")
|
|
?: error("Expected patch editor invocation")
|
|
|
|
val (selectedRepo, output) = GitSandboxEngine.applyPatchHunkEdit(patchRepo, invocation.initialContent)
|
|
|
|
assertTrue(selectedRepo.files.single { it.name == "README" }.staged)
|
|
assertTrue(selectedRepo.interactiveAddSession == null)
|
|
assertTrue(output.any { it.contains("Applied edited hunk.") })
|
|
}
|
|
|
|
@Test
|
|
fun patchAddHunkDialogHandlesAdvertisedCommands() {
|
|
val commands = listOf("y", "n", "q", "a", "d", "s", "e", "p", "P", "?")
|
|
|
|
commands.forEach { command ->
|
|
val repo = RepoState(initialized = true, files = listOf(GitFile("README", "A\nB\n", tracked = true)))
|
|
val (patchRepo, _) = GitSandboxEngine.execute(repo, "git add -p README")
|
|
val (updatedRepo, output) = GitSandboxEngine.execute(patchRepo, command)
|
|
|
|
assertFalse("$command should not be rejected", output.any { it.contains("Unknown command '$command'") })
|
|
assertTrue("$command should echo hunk prompt", output.any { it.contains("Stage this hunk") })
|
|
if (command == "e") {
|
|
assertTrue(output.any { it.contains("Opening patch editor") })
|
|
}
|
|
if (command in listOf("y", "a")) {
|
|
assertTrue(updatedRepo.files.single { it.name == "README" }.staged)
|
|
assertTrue(updatedRepo.interactiveAddSession == null)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|