Fix level setup, reword flow, and catalog scope

- create and enter the level's declared starting directory
- inspect Git state from the repository containing the active directory
- start the init level in /sandbox/git_hug and cover it with a runtime test
- apply edited reword subjects as commit messages in the in-app rebase editor
- cover rename_commit with a native interactive rebase regression test
- remove the upstream contribute call to action from the playable level catalog
- update level parity documentation
This commit is contained in:
Joe Tretter
2026-06-08 14:21:21 -05:00
parent 0d20c089ec
commit 02a23694c3
11 changed files with 194 additions and 68 deletions

View File

@@ -9,6 +9,31 @@ import java.io.File
import java.nio.file.Files
class GitSandboxEngineTest {
@Test
fun initLevelStartsInsideCreatedGitHugDirectory() {
val git = testGitBinary()
assumeTrue(git.exists() && git.canExecute())
val root = Files.createTempDirectory("githug-init-level").toFile()
try {
val runtime = GitRepositoryRuntime(root, git)
val level = initLevel()
val repo = runtime.prepareLevel(level)
val (_, pwdOutput) = runtime.execute(level, repo, "pwd")
val (initializedRepo, _) = runtime.execute(level, repo, "git init")
assertEquals("git_hug", repo.currentDir)
assertFalse(repo.initialized)
assertTrue(File(root, "init/git_hug").isDirectory)
assertEquals(listOf("/sandbox/git_hug"), pwdOutput)
assertTrue(initializedRepo.initialized)
assertTrue(File(root, "init/git_hug/.git").isDirectory)
assertTrue(level.validator(initializedRepo, "git init"))
} finally {
root.deleteRecursively()
}
}
@Test
fun statusShowsDeletedTrackedFiles() {
val repo = RepoState(
@@ -203,6 +228,36 @@ class GitSandboxEngineTest {
}
}
@Test
fun nativeGitHelpListsCommandsAndGuides() {
val git = testGitBinary()
assumeTrue(git.exists() && git.canExecute())
val root = Files.createTempDirectory("githug-help-listing").toFile()
try {
val runtime = GitRepositoryRuntime(root, git)
val level = level(
id = "help-listing-test",
title = "Help Listing Test",
description = "",
hints = emptyList(),
commandSuggestions = emptyList(),
setup = { RepoState(initialized = true) },
validator = { _, _ -> false },
)
val repo = runtime.prepareLevel(level)
val (_, commandOutput) = runtime.execute(level, repo, "git help -a")
val (_, guideOutput) = runtime.execute(level, repo, "git help -g")
assertTrue(commandOutput.any { it.contains("Main Porcelain Commands") })
assertTrue(commandOutput.any { it.contains("commit") && it.contains("Record changes") })
assertTrue(guideOutput.any { it.contains("Git concept guides") })
assertTrue(guideOutput.any { it.contains("tutorial") })
} finally {
root.deleteRecursively()
}
}
@Test
fun nativeGitExecAliasesRefreshWhenBinaryChanges() {
val git = testGitBinary()
@@ -354,6 +409,34 @@ class GitSandboxEngineTest {
}
}
@Test
fun nativeInteractiveRebaseRewordUsesEditedTodoMessage() {
val git = testGitBinary()
assumeTrue(git.exists() && git.canExecute())
val root = Files.createTempDirectory("githug-reword-editor").toFile()
try {
val runtime = GitRepositoryRuntime(root, git)
val level = renameCommitLevel()
val repo = runtime.prepareLevel(level)
val invocation = parseGitEditorInvocation("git rebase -i HEAD~2")
?: error("Expected interactive rebase editor invocation")
val todo = runtime.gitEditorInitialContent(level, repo, invocation)
val rewordedTodo = todo.replace(
Regex("(?m)^pick (\\S+) First coommit$"),
"reword $1 First commit",
)
val (updatedRepo, output) = runtime.executeGitEditorCommand(level, repo, invocation, rewordedTodo)
assertFalse(output.any { it.contains("error:", ignoreCase = true) || it.contains("fatal:", ignoreCase = true) })
assertTrue(updatedRepo.commits.any { it.message == "First commit" })
assertFalse(updatedRepo.commits.any { it.message == "First coommit" })
assertTrue(level.validator(updatedRepo, invocation.command))
} finally {
root.deleteRecursively()
}
}
@Test
fun nativeExecutableShortcutRunsScriptThroughShell() {
val git = testGitBinary()