Defer level validation while editors are open
This commit is contained in:
@@ -20,8 +20,8 @@ android {
|
||||
applicationId = "solutions.tretter.githugandroid"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 179
|
||||
versionName = "0.1.178"
|
||||
versionCode = 180
|
||||
versionName = "0.1.179"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
@@ -3,6 +3,7 @@ package solutions.tretter.githugandroid
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.junit4.createEmptyComposeRule
|
||||
import androidx.compose.ui.test.onAllNodesWithTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performSemanticsAction
|
||||
import androidx.compose.ui.test.performClick
|
||||
@@ -84,6 +85,25 @@ class GitRepositoryRuntimeInstrumentedTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun squashLevelWaitsForFinalEditorBeforeCompleting() {
|
||||
launchFreshApp().use {
|
||||
selectLevel(squashLevel())
|
||||
|
||||
submitTerminalCommand("git rebase -i HEAD~4")
|
||||
waitForGitEditorPath(".git/rebase-merge/git-rebase-todo")
|
||||
replaceGitEditorContent(squashRebaseTodo(currentGitEditorContent()))
|
||||
composeRule.onNodeWithTag("git-message-editor-save").performClick()
|
||||
|
||||
waitForGitMessageEditor()
|
||||
composeRule.onNodeWithTag("exercise-title-${squashLevel().id}").assertIsDisplayed()
|
||||
|
||||
composeRule.onNodeWithTag("git-message-editor-save").performClick()
|
||||
|
||||
waitForLevelCompletion(nextLevel = initLevel())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configLevelCompletesThroughUiWithArbitraryValues() {
|
||||
launchFreshApp().use {
|
||||
@@ -182,12 +202,28 @@ class GitRepositoryRuntimeInstrumentedTest {
|
||||
composeRule.onNodeWithTag("git-message-editor-path").assertIsDisplayed()
|
||||
}
|
||||
|
||||
private fun waitForGitMessageEditor() {
|
||||
composeRule.waitUntil(timeoutMillis = 30_000) {
|
||||
composeRule.onAllNodesWithTag("git-message-editor-content").fetchSemanticsNodes().isNotEmpty()
|
||||
}
|
||||
composeRule.onNodeWithTag("git-message-editor-content").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 squashRebaseTodo(content: String): String {
|
||||
return content
|
||||
.lineSequence()
|
||||
.mapIndexed { index, line ->
|
||||
if (index > 0 && line.startsWith("pick ")) line.replaceFirst("pick ", "squash ") else line
|
||||
}
|
||||
.joinToString("\n")
|
||||
}
|
||||
|
||||
private fun replaceGitEditorContent(content: String) {
|
||||
composeRule.onNodeWithTag("git-message-editor-content")
|
||||
.performSemanticsAction(SemanticsActions.SetText) { setText ->
|
||||
|
||||
@@ -388,11 +388,16 @@ fun GitHugApp() {
|
||||
fun applyCommandResult(raw: String, newRepo: RepoState, lines: List<String>, echoCommand: Boolean) {
|
||||
val startedAt = System.nanoTime()
|
||||
val levelForResult = currentLevel
|
||||
val solvedAfterCommand = levelForResult.validator(newRepo, raw)
|
||||
val validationBlockedByEditor = editorState != null || gitMessageEditorState != null
|
||||
val solvedAfterCommand = if (validationBlockedByEditor) {
|
||||
false
|
||||
} else {
|
||||
levelForResult.validator(newRepo, raw)
|
||||
}
|
||||
val wasAlreadyCompleted = currentLevel.id in completedLevels
|
||||
AppLog.d(
|
||||
"GitHugApp",
|
||||
"Command='$raw' level=${levelForResult.id} solved=$solvedAfterCommand alreadyCompleted=$wasAlreadyCompleted " +
|
||||
"Command='$raw' level=${levelForResult.id} solved=$solvedAfterCommand validationBlockedByEditor=$validationBlockedByEditor alreadyCompleted=$wasAlreadyCompleted " +
|
||||
"completedBefore=${completedLevels.sorted()} outputLineCount=${lines.size} repo=${newRepo.diagnosticSnapshot()}",
|
||||
)
|
||||
val newOutput = buildList {
|
||||
@@ -519,14 +524,13 @@ fun GitHugApp() {
|
||||
invocation = state.invocation,
|
||||
message = state.content,
|
||||
)
|
||||
gitMessageEditorState = null
|
||||
applyCommandResult(state.invocation.command, result.repo, result.outputLines, echoCommand = false)
|
||||
result.nextEditor?.let { nextEditor ->
|
||||
gitMessageEditorState = GitMessageEditorState(
|
||||
gitMessageEditorState = result.nextEditor?.let { nextEditor ->
|
||||
GitMessageEditorState(
|
||||
invocation = nextEditor.invocation,
|
||||
content = nextEditor.content,
|
||||
)
|
||||
}
|
||||
applyCommandResult(state.invocation.command, result.repo, result.outputLines, echoCommand = false)
|
||||
}
|
||||
|
||||
fun runCommand() {
|
||||
|
||||
Reference in New Issue
Block a user