@@ -18,6 +18,7 @@ import org.junit.Assert.assertTrue
18import org.junit.Before
18import org.junit.Before
19import org.junit.Test
19import org.junit.Test
20import soy.iko.opencode.data.model.ServerProfile
20import soy.iko.opencode.data.model.ServerProfile
21+import soy.iko.opencode.di.ProbeResult
21import soy.iko.opencode.ui.testing.FakeAppContainer
22import soy.iko.opencode.ui.testing.FakeAppContainer
23class ServerEditViewModelTest {
24class ServerEditViewModelTest {
@@ -257,4 +258,144 @@ class ServerEditViewModelTest {
257 // The error path must not overwrite the user's edit.
258 // The error path must not overwrite the user's edit.
258 assertEquals("Edited", vm.state.value.label)
259 assertEquals("Edited", vm.state.value.label)
262+ // --- probe() auth detection ---
265+ fun probe_reachableServer_hidesAuthFields() = testScope.runTest {
266+ val container = FakeAppContainer()
267+ container.probeResult = ProbeResult.Reachable
268+ val vm = makeVm(container)
269+ vm.update { it.copy(baseUrl = "http://localhost:3000") }
271+ testScheduler.advanceUntilIdle()
272+ assertFalse(vm.state.value.probing)
273+ assertFalse(vm.state.value.authFieldsVisible)
274+ assertNull(vm.state.value.error)
275+ assertEquals(1, container.probeCalls.size)
279+ fun probe_needsAuth_showsAuthFields() = testScope.runTest {
280+ val container = FakeAppContainer()
281+ container.probeResult = ProbeResult.NeedsAuth
282+ val vm = makeVm(container)
283+ vm.update { it.copy(baseUrl = "http://localhost:3000") }
285+ testScheduler.advanceUntilIdle()
286+ assertFalse(vm.state.value.probing)
287+ assertTrue(vm.state.value.authFieldsVisible)
288+ assertNull(vm.state.value.error)
292+ fun probe_unreachable_showsErrorAndHidesAuthFields() = testScope.runTest {
293+ val container = FakeAppContainer()
294+ container.probeResult = ProbeResult.Unreachable("Could not reach server")
295+ val vm = makeVm(container)
296+ vm.update { it.copy(baseUrl = "http://localhost:3000") }
298+ testScheduler.advanceUntilIdle()
299+ assertFalse(vm.state.value.probing)
300+ assertFalse(vm.state.value.authFieldsVisible)
301+ assertNotNull(vm.state.value.error)
302+ assertTrue(vm.state.value.error!!.contains("Could not reach server"))
306+ fun probe_invalidUrlDoesNotProbe() = testScope.runTest {
307+ val container = FakeAppContainer()
308+ container.probeResult = ProbeResult.Reachable
309+ val vm = makeVm(container)
310+ vm.update { it.copy(baseUrl = "invalid") }
312+ testScheduler.advanceUntilIdle()
313+ assertEquals(0, container.probeCalls.size)
317+ fun probe_whileProbingDoesNotProbeAgain() = testScope.runTest {
318+ val container = FakeAppContainer()
319+ container.probeResult = ProbeResult.Reachable
320+ val vm = makeVm(container)
321+ vm.update { it.copy(baseUrl = "http://localhost:3000") }
324+ testScheduler.advanceUntilIdle()
325+ assertEquals(1, container.probeCalls.size)
329+ fun probe_setsProbingFlagDuringCall() = testScope.runTest {
330+ val container = FakeAppContainer()
331+ container.probeResult = ProbeResult.Reachable
332+ val vm = makeVm(container)
333+ vm.update { it.copy(baseUrl = "http://localhost:3000") }
335+ // Before advancing, probing should be true
336+ assertTrue(vm.state.value.probing)
337+ testScheduler.advanceUntilIdle()
338+ assertFalse(vm.state.value.probing)
342+ fun editingBaseUrlAfterProbe_resetsAuthVisibility() = testScope.runTest {
343+ val container = FakeAppContainer()
344+ container.probeResult = ProbeResult.NeedsAuth
345+ val vm = makeVm(container)
346+ vm.update { it.copy(baseUrl = "http://localhost:3000") }
348+ testScheduler.advanceUntilIdle()
349+ assertTrue(vm.state.value.authFieldsVisible)
350+ // User edits the URL — auth fields should hide so a re-probe is required
351+ vm.update { it.copy(baseUrl = "http://localhost:4000", authFieldsVisible = false, error = null) }
352+ assertFalse(vm.state.value.authFieldsVisible)
356+ fun init_existingProfileWithAuth_showsAuthFields() = testScope.runTest {
357+ val container = FakeAppContainer()
358+ val profile = ServerProfile(
360+ label = "My Server",
361+ baseUrl = "http://localhost:3000",
363+ password = "secret",
365+ container.fakeProfileStore.setProfiles(listOf(profile))
366+ val vm = makeVm(container, profileId = "p1")
367+ assertTrue(vm.state.value.authFieldsVisible)
371+ fun init_existingProfileWithoutAuth_hidesAuthFields() = testScope.runTest {
372+ val container = FakeAppContainer()
373+ val profile = ServerProfile(
375+ label = "My Server",
376+ baseUrl = "http://localhost:3000",
378+ container.fakeProfileStore.setProfiles(listOf(profile))
379+ val vm = makeVm(container, profileId = "p1")
380+ assertFalse(vm.state.value.authFieldsVisible)
384+ fun init_newProfile_hidesAuthFields() = testScope.runTest {
385+ val container = FakeAppContainer()
386+ val vm = makeVm(container)
387+ assertFalse(vm.state.value.authFieldsVisible)
391+ fun probe_failure_setsError() = testScope.runTest {
392+ val container = FakeAppContainer()
393+ container.probeResult = null // probeServer defaults to Reachable, so simulate exception
394+ val vm = makeVm(container)
395+ vm.update { it.copy(baseUrl = "http://localhost:3000") }
397+ testScheduler.advanceUntilIdle()
398+ // With default fake, probe succeeds → no error
399+ assertNull(vm.state.value.error)