Fix Git editor reword workflow and UI coverage
- show Git editor file paths instead of the submitted git command - surface follow-up commit message editors during interactive rebase reword - add rename-commit UI tests for editor and amend-message solution paths - add broader embedded level solution scenarios for alternate Git workflows
This commit is contained in:
@@ -4,11 +4,16 @@ import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.junit4.createEmptyComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performSemanticsAction
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performImeAction
|
||||
import androidx.compose.ui.test.performScrollTo
|
||||
import androidx.compose.ui.test.performTextClearance
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.compose.ui.semantics.SemanticsActions
|
||||
import androidx.compose.ui.semantics.SemanticsProperties
|
||||
import androidx.compose.ui.semantics.getOrNull
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
@@ -44,12 +49,41 @@ class GitRepositoryRuntimeInstrumentedTest {
|
||||
launchFreshApp().use {
|
||||
allGithugLevels().forEachIndexed { index, level ->
|
||||
waitForExercise(level)
|
||||
level.testCases.first().commands.forEach(::submitTerminalCommand)
|
||||
if (level.id == renameCommitLevel().id) {
|
||||
completeRenameCommitWithEditor()
|
||||
} else {
|
||||
level.testCases.first().commands.forEach(::submitTerminalCommand)
|
||||
}
|
||||
waitForLevelCompletion(nextLevel = allGithugLevels().getOrNull(index + 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameCommitLevelCompletesThroughUiEditor() {
|
||||
launchFreshApp().use {
|
||||
selectLevel(renameCommitLevel())
|
||||
|
||||
completeRenameCommitWithEditor()
|
||||
|
||||
waitForLevelCompletion(nextLevel = initLevel())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameCommitLevelCompletesThroughMessageOptionAfterReword() {
|
||||
launchFreshApp().use {
|
||||
selectLevel(renameCommitLevel())
|
||||
|
||||
startRenameCommitReword()
|
||||
composeRule.onNodeWithTag("git-message-editor-dismiss").performClick()
|
||||
submitTerminalCommand("git commit --amend -m \"First commit\"")
|
||||
submitTerminalCommand("git rebase --continue")
|
||||
|
||||
waitForLevelCompletion(nextLevel = initLevel())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configLevelCompletesThroughUiWithArbitraryValues() {
|
||||
launchFreshApp().use {
|
||||
@@ -111,6 +145,56 @@ class GitRepositoryRuntimeInstrumentedTest {
|
||||
composeRule.onNodeWithTag("exercise-title-${nextLevel.id}").assertIsDisplayed()
|
||||
}
|
||||
|
||||
private fun selectLevel(level: Level) {
|
||||
composeRule.onNodeWithTag("level-${level.id}")
|
||||
.performScrollTo()
|
||||
.performClick()
|
||||
waitForExercise(level)
|
||||
composeRule.waitUntil(timeoutMillis = 30_000) {
|
||||
composeRule.onAllNodes(hasText("Loaded level: ${level.title}", substring = true))
|
||||
.fetchSemanticsNodes()
|
||||
.isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private fun completeRenameCommitWithEditor() {
|
||||
startRenameCommitReword()
|
||||
waitForGitEditorPath(".git/COMMIT_EDITMSG")
|
||||
replaceGitEditorContent(
|
||||
currentGitEditorContent().replaceFirst("First coommit", "First commit"),
|
||||
)
|
||||
composeRule.onNodeWithTag("git-message-editor-save").performClick()
|
||||
}
|
||||
|
||||
private fun startRenameCommitReword() {
|
||||
submitTerminalCommand("git rebase -i HEAD~2")
|
||||
waitForGitEditorPath(".git/rebase-merge/git-rebase-todo")
|
||||
replaceGitEditorContent(
|
||||
currentGitEditorContent().replaceFirst(Regex("(?m)^pick "), "reword "),
|
||||
)
|
||||
composeRule.onNodeWithTag("git-message-editor-save").performClick()
|
||||
}
|
||||
|
||||
private fun waitForGitEditorPath(path: String) {
|
||||
composeRule.waitUntil(timeoutMillis = 30_000) {
|
||||
composeRule.onAllNodes(hasText(path, substring = true)).fetchSemanticsNodes().isNotEmpty()
|
||||
}
|
||||
composeRule.onNodeWithTag("git-message-editor-path").assertIsDisplayed()
|
||||
}
|
||||
|
||||
private fun currentGitEditorContent(): String {
|
||||
val node = composeRule.onNodeWithTag("git-message-editor-content").fetchSemanticsNode()
|
||||
return node.config.getOrNull(SemanticsProperties.EditableText)?.text
|
||||
?: error("Expected Git editor content semantics")
|
||||
}
|
||||
|
||||
private fun replaceGitEditorContent(content: String) {
|
||||
composeRule.onNodeWithTag("git-message-editor-content")
|
||||
.performSemanticsAction(SemanticsActions.SetText) { setText ->
|
||||
setText(AnnotatedString(content))
|
||||
}
|
||||
}
|
||||
|
||||
private fun submitTerminalCommand(command: String) {
|
||||
val input = composeRule.onNodeWithTag("terminal-command-input")
|
||||
input.performClick()
|
||||
|
||||
Reference in New Issue
Block a user